C++ OpenCV Image Processing

Image Filtering

Image filtering is a basic operation in image processing, mainly used to remove noise from images or enhance certain features. Common filtering methods include mean filter, Gaussian filter, median filter, and custom filters.

Mean Filter

Mean filtering is a simple linear filtering method that replaces each pixel value in an image with the average of all pixel values in its neighborhood. This method can effectively remove noise, but it also blurs the image.

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

Gaussian Filter

Gaussian filtering is a nonlinear filtering method that uses a Gaussian function to calculate the weights of pixels in the neighborhood, thereby smoothing the image. While removing noise, Gaussian filtering can better preserve edge information in the image.

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

Median Filter

Median filtering is a nonlinear filtering method that replaces each pixel value in an image with the median of all pixel values in its neighborhood. This method is very effective at removing salt-and-pepper noise.

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

Custom Filter

OpenCV allows users to customize the filter kernel. Throughcv::filter2Dthe function, custom filtering operations can be implemented.

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

Image Edge Detection

Edge detection is an important task in image processing, used to identify the boundaries of objects in an image. Common edge detection methods include the Sobel operator and Canny edge detection.

Sobel Operator

The Sobel operator is a gradient-based edge detection method that can detect horizontal and vertical edges in an image.

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 Edge Detection

Canny edge detection is a multi-stage edge detection algorithm that can effectively detect edges in images and is highly robust to noise.

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

Image Morphological Operations

Morphological operations are a series of operations based on image shape, often used for tasks such as foreground and background separation and noise removal. Common morphological operations include erosion, dilation, opening, closing, and morphological gradient.

Erosion

The erosion operation can eliminate small objects or details in an image, making foreground objects smaller.

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

Dilation

The dilation operation can enlarge foreground objects in an image, often used to fill holes in foreground objects.

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

Opening Operation

Opening is an operation of erosion followed by dilation, often used to remove small objects or noise.

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

Closing Operation

Closing is an operation of dilation followed by erosion, often used to fill small holes in foreground objects.

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

Morphological Gradient

The morphological gradient is the difference between dilation and erosion, and can be used to extract object edges.

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

Image Thresholding

Image thresholding is the process of converting an image into a binary image, often used for image segmentation. Common thresholding methods include binarization, adaptive thresholding, and Otsu's method.

Binarization

Binarization divides pixel values in an image into two classes according to a set threshold, usually used for simple image segmentation.

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

Adaptive Threshold

Adaptive threshold dynamically calculates the threshold based on local regions of the image, suitable for images with uneven illumination.

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

Otsu's Thresholding Method

Otsu's method is an automatic threshold determination method, suitable for images with bimodal histograms.

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

Image Histogram

A histogram is a tool used in image processing to analyze the brightness distribution of an image. Common histogram operations include calculating histograms, histogram equalization, and histogram comparison.

Calculating Histogram

A histogram can reflect the distribution of pixel values in an image.

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);

Histogram Equalization

Histogram equalization can enhance the contrast of an image, making the brightness distribution more uniform.

cv::equalizeHist(src, dst);

Histogram Comparison

Histogram comparison can be used to compare the similarity of two images.

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

Examples

Common image processing operations in OpenCV include filtering, edge detection, thresholding, morphological operations, and contour detection. With these techniques, you can implement more complex image processing tasks.

The following are common image processing operations in C++ OpenCV and their code examples:

1. Image Filtering

Image filtering is used to remove noise or enhance image features.

1.1 Mean Filter

Example

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

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "Error: Unable to load image, please check if the path is correct." << endl;
        return -1;
    }

    // Mean filter
    Mat blurredImage;
    blur(image, blurredImage, Size(5, 5)); // 5x5 kernel

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

    return 0;
}

1.2 Gaussian Filter

Example

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

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "Error: Unable to load image, please check if the path is correct." << endl;
        return -1;
    }

    // Gaussian filter
    Mat gaussianBlurredImage;
    GaussianBlur(image, gaussianBlurredImage, Size(5, 5), 0); // 5x5 kernel

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

    return 0;
}

1.3 Median Filter

Example

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

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "Error: Unable to load image, please check if the path is correct." << endl;
        return -1;
    }

    // Median filter
    Mat medianBlurredImage;
    medianBlur(image, medianBlurredImage, 5); // Kernel size is 5

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

    return 0;
}

2. Edge Detection

Edge detection is used to extract edge information from images.

2.1 Canny Edge Detection

Example

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

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "Error: Unable to load image, please check if the path is correct." << endl;
        return -1;
    }

    // Convert to grayscale image
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // Canny edge detection
    Mat edges;
    Canny(grayImage, edges, 100, 200); // Threshold 1 and threshold 2

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

    return 0;
}

3. Image Thresholding

Thresholding is used to convert an image into a binary image.

3.1 Simple Thresholding

Example

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

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "Error: Unable to load image, please check if the path is correct." << endl;
        return -1;
    }

    // Convert to grayscale image
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // Simple thresholding
    Mat binaryImage;
    threshold(grayImage, binaryImage, 127, 255, THRESH_BINARY);

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

    return 0;
}

3.2 Adaptive Thresholding

Example

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

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "Error: Unable to load image, please check if the path is correct." << endl;
        return -1;
    }

    // Convert to grayscale image
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // Adaptive thresholding
    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. Morphological Operations

Morphological operations are used to process the shape and structure of images.

4.1 Erosion and Dilation

Example

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

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "Error: Unable to load image, please check if the path is correct." << endl;
        return -1;
    }

    // Convert to grayscale image
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // Binarization
    Mat binaryImage;
    threshold(grayImage, binaryImage, 127, 255, THRESH_BINARY);

    // Erosion operation
    Mat erodedImage;
    Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
    erode(binaryImage, erodedImage, kernel);

    // Dilation operation
    Mat dilatedImage;
    dilate(binaryImage, dilatedImage, kernel);

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

    return 0;
}

5. Contour Detection

Contour detection is used to extract object contours in images.

Example


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

using namespace cv;
using namespace std;

int main() {
    Mat image = imread("test.jpg");
    if (image.empty()) {
        cout << "Error: Unable to load image, please check if the path is correct." << endl;
        return -1;
    }

    // Convert to grayscale image
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // Binarization
    Mat binaryImage;
    threshold(grayImage, binaryImage, 127, 255, THRESH_BINARY);

    // Find contours
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(binaryImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);

    // Draw contours
    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;
}
Other Extensions