现在位置: 首页 > OpenCV 教程 > 正文

C++ OpenCV 图像处理

图像滤波

图像滤波是图像处理中的一种基本操作,主要用于去除图像中的噪声或增强图像的某些特征。常见的滤波方法包括均值滤波、高斯滤波、中值滤波以及自定义滤波器。

均值滤波

均值滤波是一种简单的线性滤波方法,它将图像中每个像素的值替换为其邻域内所有像素值的平均值。这种方法可以有效去除噪声,但也会使图像变得模糊。

cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat dst;
cv::blur(src, dst, cv::Size(3, 3));  // 3x3的均值滤波

高斯滤波

高斯滤波是一种非线性滤波方法,它使用高斯函数来计算邻域内像素的权重,从而对图像进行平滑处理。高斯滤波在去除噪声的同时,能够更好地保留图像的边缘信息。

cv::GaussianBlur(src, dst, cv::Size(5, 5), 0);  // 5x5的高斯滤波

中值滤波

中值滤波是一种非线性滤波方法,它将图像中每个像素的值替换为其邻域内所有像素值的中值。这种方法在去除椒盐噪声时效果非常好。

cv::medianBlur(src, dst, 5);  // 5x5的中值滤波

自定义滤波器

OpenCV允许用户自定义滤波器核,通过cv::filter2D函数可以实现自定义滤波操作。

cv::Mat kernel = (cv::Mat_<float>(3, 3) << 1, 0, -1, 0, 0, 0, -1, 0, 1);
cv::filter2D(src, dst, -1, kernel);

图像边缘检测

边缘检测是图像处理中的一个重要任务,用于识别图像中物体的边界。常用的边缘检测方法包括Sobel算子和Canny边缘检测。

Sobel算子

Sobel算子是一种基于梯度的边缘检测方法,它可以检测图像中的水平和垂直边缘。

cv::Mat grad_x, grad_y;
cv::Sobel(src, grad_x, CV_16S, 1, 0);  // 水平方向
cv::Sobel(src, grad_y, CV_16S, 0, 1);  // 垂直方向
cv::convertScaleAbs(grad_x, grad_x);
cv::convertScaleAbs(grad_y, grad_y);
cv::addWeighted(grad_x, 0.5, grad_y, 0.5, 0, dst);  // 合并结果

Canny 边缘检测

Canny 边缘检测是一种多阶段的边缘检测算法,它能够有效地检测出图像中的边缘,并且对噪声具有较强的鲁棒性。

cv::Canny(src, dst, 100, 200);  // 阈值1=100,阈值2=200

图像形态学操作

形态学操作是基于图像形状的一系列操作,常用于图像的前景和背景分离、噪声去除等任务。常见的形态学操作包括腐蚀、膨胀、开运算、闭运算和形态学梯度。

腐蚀

腐蚀操作可以消除图像中的小物体或细节,使得前景物体变小。

cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
cv::erode(src, dst, kernel);

膨胀

膨胀操作可以扩大图像中的前景物体,常用于填补前景物体中的空洞。

cv::dilate(src, dst, kernel);

开运算

开运算是先腐蚀后膨胀的操作,常用于去除小物体或噪声。

cv::morphologyEx(src, dst, cv::MORPH_OPEN, kernel);

闭运算

闭运算是先膨胀后腐蚀的操作,常用于填补前景物体中的小孔。

cv::morphologyEx(src, dst, cv::MORPH_CLOSE, kernel);

形态学梯度

形态学梯度是膨胀和腐蚀的差值,可以用于提取物体的边缘。

cv::morphologyEx(src, dst, cv::MORPH_GRADIENT, kernel);

图像阈值化

图像阈值化是将图像转换为二值图像的过程,常用于图像分割。常见的阈值化方法包括二值化、自适应阈值和Otsu阈值法。

二值化

二值化是将图像中的像素值根据设定的阈值分为两类,通常用于简单的图像分割。

cv::threshold(src, dst, 127, 255, cv::THRESH_BINARY);

自适应阈值

自适应阈值根据图像的局部区域动态计算阈值,适用于光照不均匀的图像。

cv::adaptiveThreshold(src, dst, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 11, 2);

Otsu阈值法

Otsu阈值法是一种自动确定阈值的方法,适用于双峰直方图的图像。

cv::threshold(src, dst, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);

图像直方图

直方图是图像处理中用于分析图像亮度分布的工具。常见的直方图操作包括计算直方图、直方图均衡化和直方图对比。

计算直方图

直方图可以反映图像中像素值的分布情况。

cv::Mat hist;
int histSize = 256;
float range[] = {0, 256};
const float* histRange = {range};
cv::calcHist(&src, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange);

直方图均衡化

直方图均衡化可以增强图像的对比度,使得图像的亮度分布更加均匀。

cv::equalizeHist(src, dst);

直方图对比

直方图对比可以用于比较两幅图像的相似性。

double compare = cv::compareHist(hist1, hist2, cv::HISTCMP_CORREL);

实例

OpenCV 中常见的图像处理操作,包括滤波、边缘检测、阈值化、形态学操作和轮廓检测。通过这些技术,你可以实现更复杂的图像处理任务。

以下是 C++ OpenCV 中常见的图像处理操作及其代码示例:

1. 图像滤波

图像滤波用于去除噪声或增强图像特征。

1.1 均值滤波

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 均值滤波
    Mat blurredImage;
    blur(image, blurredImage, Size(5, 5)); // 5x5 的核

    imshow("Original Image", image);
    imshow("Blurred Image", blurredImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

1.2 高斯滤波

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 高斯滤波
    Mat gaussianBlurredImage;
    GaussianBlur(image, gaussianBlurredImage, Size(5, 5), 0); // 5x5 的核

    imshow("Original Image", image);
    imshow("Gaussian Blurred Image", gaussianBlurredImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

1.3 中值滤波

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 中值滤波
    Mat medianBlurredImage;
    medianBlur(image, medianBlurredImage, 5); // 核大小为 5

    imshow("Original Image", image);
    imshow("Median Blurred Image", medianBlurredImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

2. 边缘检测

边缘检测用于提取图像中的边缘信息。

2.1 Canny 边缘检测

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 转换为灰度图像
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // Canny 边缘检测
    Mat edges;
    Canny(grayImage, edges, 100, 200); // 阈值1和阈值2

    imshow("Original Image", image);
    imshow("Canny Edges", edges);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

3. 图像阈值化

阈值化用于将图像转换为二值图像。

3.1 简单阈值化

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 转换为灰度图像
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // 简单阈值化
    Mat binaryImage;
    threshold(grayImage, binaryImage, 127, 255, THRESH_BINARY);

    imshow("Original Image", image);
    imshow("Binary Image", binaryImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

3.2 自适应阈值化

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 转换为灰度图像
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // 自适应阈值化
    Mat adaptiveBinaryImage;
    adaptiveThreshold(grayImage, adaptiveBinaryImage, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 11, 2);

    imshow("Original Image", image);
    imshow("Adaptive Binary Image", adaptiveBinaryImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

4. 形态学操作

形态学操作用于处理图像的形状和结构。

4.1 腐蚀与膨胀

实例

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 转换为灰度图像
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // 二值化
    Mat binaryImage;
    threshold(grayImage, binaryImage, 127, 255, THRESH_BINARY);

    // 腐蚀操作
    Mat erodedImage;
    Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
    erode(binaryImage, erodedImage, kernel);

    // 膨胀操作
    Mat dilatedImage;
    dilate(binaryImage, dilatedImage, kernel);

    imshow("Original Image", image);
    imshow("Eroded Image", erodedImage);
    imshow("Dilated Image", dilatedImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

5. 轮廓检测

轮廓检测用于提取图像中的对象轮廓。

实例


#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 转换为灰度图像
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // 二值化
    Mat binaryImage;
    threshold(grayImage, binaryImage, 127, 255, THRESH_BINARY);

    // 查找轮廓
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(binaryImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

    // 绘制轮廓
    Mat contourImage = Mat::zeros(image.size(), CV_8UC3);
    for (size_t i = 0; i < contours.size(); i++) {
        drawContours(contourImage, contours, i, Scalar(0, 255, 0), 2);
    }

    imshow("Original Image", image);
    imshow("Contours", contourImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}