opencv 图像处理(一)

1. Mat --> QImage
cpp 复制代码
QImage mat2QImage(const cv::Mat &mat)
{

    if(mat.empty()) return QImage();

    if(mat.type == CV_8UC3)
    {
        // BGR -> RGB
        cv::Mat rgb;
        cv::cvtColor(mat, rgb, cv::COLOR_BGR2RGB);
        return QImage(rgb.data, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888).copy();
    }
    else if(mat.type == CV_8UC1)
    {
        // BGR -> GRAY
        cv::Mat gray;
        cv::cvtColor(mat, gray, cv::COLOR_BGR2GRAY);
        return QImage(gray.data, gray.cols, gray.rows, gray.step, QImage::Fomat_RGB888).copy();
    }

    return QImage();
}
2. QImage ---> Mat
cpp 复制代码
cv::Mat qImage2Mat(const QImage &img)
{
    if(img.isNull()) return cv::Mat();

    if(img.format() == QImage::Format_RGB888)
    {
        cv::Mat mat(img.height(), img.width(), CV_8UC3, (void*)img.bits(), img.bytesPerLine());
        cv::Mat bgr;
        cv::cvtColor(mat, bgr, cv::COLOR_RGB2BGR);
        return bgr;
    }

    if(img.format() == QImage::Format_Grayscale8)
    {
        cv::Mat mat(img.height(), img.width(), CV_8UC1, (void *)img.bits(),img.byesPerLine());
        return mat;
    }

    return cv::Mat();
}
3. 在label显示Mat
cpp 复制代码
void MainWindow::showMat(const cv::Mat& mat)
{
    QImage img = mat2QImage(mat);
    ui->label->setPixmap(QPixmap::fromQImage(img).scaled(ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransFormation));

}
3. 读写与显示
cpp 复制代码
// 读取图像
cv::Mat matBgr = cv::imread("test.jpg");
// 灰度读取
cv::Mat gray = cv::imread("test.jpg", cv::IMREAD_GRAYSCALE);

//显示窗口
cv::imshow("matbgr", matBgr);
cv::waitKey(0);  // 等待按键
cv::destoryAllwindows()  // 销毁所有窗口

//保存
cv::imwrite("out.jpg", img);
4. 滤波(均值、高斯、中植、双边)
cpp 复制代码
//均值滤波   cv::Size()  必须奇数, size越大越模糊
void onblur()
{
    cv::blur(srcMat, srcMat, cv::Size(5, 5));
    showMat(srcMat);
}

void blur(InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT)
  • srcMat:输入图像;第二个 srcMat:输出图像(原地覆盖)

  • cv::Size(5,5):5×5 的卷积核

    普通均匀噪声

cpp 复制代码
// 高斯滤波
void onGaussian()
{
    cv::GaussianBlur(srcMat, srcMat, cv::Size(5,5), 1.2);
    showMat(srcMat);
}

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT)
  • Size(5,5):高斯核大小,必须是奇数(3,5,7...)

  • 1.2:sigmaX,X 方向高斯标准差;sigmaY=0 默认和 sigmaX 相等

    重点:如果 ksize 填 Size (0,0),OpenCV 会自动根据 sigma 计算核大小。

    高斯噪声(图像里淡淡的均匀噪点)

cpp 复制代码
//中值滤波
void onMedian()
{
    cv::MedianBlur(srcMat, srcMat, 5);
    showMat(srcMat);
}

void medianBlur(InputArray src, OutputArray dst, int ksize)

5:核尺寸,必须是奇数,这里是 5×5 窗口

适合:图像里随机的黑白噪点(椒盐噪声)

cpp 复制代码
// 双边滤波
void onBilateral()
{
    cv::bilateralFilter(srcMat, srcMat, 9, 75, 75);
    showMat(srcMat);
}

void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT)

参数解释:

  1. d=9:滤波时使用的邻域直径;d≤0 时由 sigmaSpace 自动计算
  2. sigmaColor=75:颜色空间标准差。值越大,颜色差异大的像素也会被一起平均
  3. sigmaSpace=75:坐标空间标准差。值越大,更远的像素参与计算

适合:需要保留轮廓、边缘的场景(人像、物体轮廓)

缺点:速度很慢,计算量大;对椒盐噪声效果差

滤波 核心 擅长噪声 边缘 速度
均值 blur 窗口平均值 均匀噪声 严重模糊 快
高斯 GaussianBlur 高斯加权平均 高斯噪声 轻微模糊 较快
中值 medianBlur 窗口中位数 椒盐噪声(黑白噪点) 模糊 中等
双边 bilateralFilter 空间 + 灰度双重高斯 平缓区域噪声 ✅ 保留边缘 很慢
  1. 几何变换(缩放、平移、旋转、翻转)
cpp 复制代码
//缩放
cv::resize(srcMat, dstMat, cv::Size(), 0.6, 0.6, cv::INTER_LINEAR);

void cv::resize(
    cv::InputArray src,        // 输入图
    cv::OutputArray dst,       // 输出图
    cv::Size dsize,            // 目标尺寸 (宽,高)
    double fx = 0,             // x方向缩放系数
    double fy = 0,             // y方向缩放系数
    int interpolation = cv::INTER_LINEAR  // 插值方式
);

重点:dsize 和 fx/fy 二选一

  • 写了 dsize,fx、fy 自动忽略
  • dsize 填 cv::Size(0,0),才会使用 fx、fy 计算大小OpenCV
cpp 复制代码
//翻转
cv::flip(srcMat, dstMat, 1);  // 1 水平翻转  0 垂直翻转  -1 同时翻转


// 旋转
void onRotate()
{
    cv::Point2f center(srcMat.cols/2.of, srcMat.rows/2.0f);
    //  以center为中心,旋转30度,缩放0.8 得到旋转矩阵
    cv::Mat rotMat = cv::getRotationMatrix2D(center, 30, 0.8);
    cv::warpAffine(srcMat, ddstMat, rotMat, srMat.size());
    showMat(dstMat);
}

// 平移
void onShift()
{
    cv::Mat transMat = (cv::Mat_<float>(2,3) << 1,0,20, 0,1,20);
    cv::warpAffine(srcMat, dstMat, transMat, srcMat.size());
    showMat(srcMat);
}

仿射变换:可以实现平移、旋转、缩放、斜切(错切);特点:直线保持直线、平行线依旧平行;矩形可以变成平行四边形

void cv::warpAffine(

cv::InputArray src, // 输入图

cv::OutputArray dst, // 输出图

cv::InputArray M, // 【2行3列 float矩阵】仿射矩阵

cv::Size dsize, // 输出图尺寸 (宽,高)

int flags = cv::INTER_LINEAR, // 插值,和resize一样

int borderMode = cv::BORDER_CONSTANT,

const cv::Scalar &borderValue = cv::Scalar(0,0,0) // 填充边界颜色,默认黑色

);

生成旋转矩阵(最常用)

Mat getRotationMatrix2D(Point2f center, double angle, double scale);

相关推荐
qq_364682151 小时前
AI如何将录音内容自动整理成Excel清单
人工智能·excel
国科安芯1 小时前
从点火到入轨的毫秒尺度:商业运载火箭飞行时序控制中的抗辐射MCU可靠性边界—— 面向短时高可靠任务的单粒子效应证据与架构分析
网络·人工智能·单片机·嵌入式硬件·架构·火箭·抗辐射
吠品1 小时前
78B 只激活 3.46B,Kolibri 给模型选型上了一课
人工智能·单片机·嵌入式硬件
玩美数据1 小时前
全球数据分析服务竞争态势与战略机遇深度解读
大数据·人工智能
Maynor9961 小时前
AI 表情包/热梗视频工具怎么选:RemixMeme 对比通用 AI 视频|remixmeme.com
人工智能·ai·短视频·tiktok·ai视频·表情包·remixmeme
老木避暑研究所1 小时前
负氧离子数据的采集、清洗与可视化:一套可复用的环境监测数据分析模板
前端·人工智能·数据分析
AI领域分享1 小时前
批量做漫剧视频选什么工具?知漫剧多集任务实测
大数据·人工智能·音视频
Dola_Zou1 小时前
从二进制加固到离线鉴权 工业边缘AI安全防御架构
人工智能·安全·ai·架构·软件加密
wshzd1 小时前
LLM之Agent(122)|DeepSeek-Harness(二十九)测试哲学:Verify the World, not the Self-Report
人工智能