OpenCV基础操作与图像处理

目录

一、基础操作

[1. 图像的基本操作](#1. 图像的基本操作)

[1.1 读取、显示和保存图像](#1.1 读取、显示和保存图像)

[1.2 图像的基本属性](#1.2 图像的基本属性)

[1.3 图像的创建与初始化](#1.3 图像的创建与初始化)

[1.4 图像的像素操作](#1.4 图像的像素操作)

[2. 图像的几何变换](#2. 图像的几何变换)

[2.1 缩放、旋转、平移、翻转](#2.1 缩放、旋转、平移、翻转)

[2.2 仿射变换与透视变换](#2.2 仿射变换与透视变换)

3.图像的颜色空间转换

[3.1 RGB、灰度、HSV等颜色空间](#3.1 RGB、灰度、HSV等颜色空间)

[3.2 颜色空间转换](#3.2 颜色空间转换)

[3.3 通道分离与合并](#3.3 通道分离与合并)

[4. 实例](#4. 实例)

[4.1 图像的读取与显示](#4.1 图像的读取与显示)

[4.2 图像的保存](#4.2 图像的保存)

[4.3 获取图像属性](#4.3 获取图像属性)

[4.4 访问和修改像素值](#4.4 访问和修改像素值)

[4.5 图像颜色空间转换](#4.5 图像颜色空间转换)

[4.6 图像的裁剪与缩放](#4.6 图像的裁剪与缩放)

[4.7 图像的复制与克隆](#4.7 图像的复制与克隆)

[4.8 图像的几何变换](#4.8 图像的几何变换)

二、图像处理

[1. 图像滤波](#1. 图像滤波)

[1.1 均值滤波](#1.1 均值滤波)

[1.2 高斯滤波](#1.2 高斯滤波)

[1.3 中值滤波](#1.3 中值滤波)

[1.4 自定义滤波器](#1.4 自定义滤波器)

[2. 图像边缘检测](#2. 图像边缘检测)

[2.1 Sobel算子](#2.1 Sobel算子)

[2.2 Canny 边缘检测](#2.2 Canny 边缘检测)

[3. 图像形态学操作](#3. 图像形态学操作)

[3.1 腐蚀](#3.1 腐蚀)

[3.2 膨胀](#3.2 膨胀)

[3.3 开运算](#3.3 开运算)

[3.4 闭运算](#3.4 闭运算)

形态学梯度

[4. 图像阈值化](#4. 图像阈值化)

[4.1 二值化](#4.1 二值化)

[4.2 自适应阈值](#4.2 自适应阈值)

[4.3 Otsu阈值法](#4.3 Otsu阈值法)

[5. 图像直方图](#5. 图像直方图)

[5.1 计算直方图](#5.1 计算直方图)

[5.2 直方图均衡化](#5.2 直方图均衡化)

[5.3 直方图对比](#5.3 直方图对比)

[6. 实例](#6. 实例)

[6.1 图像滤波](#6.1 图像滤波)

[6.2 边缘检测](#6.2 边缘检测)

[6.3 图像阈值化](#6.3 图像阈值化)

[6.4 形态学操作](#6.4 形态学操作)

[6.5 轮廓检测](#6.5 轮廓检测)


一、基础操作

1. 图像的基本操作

1.1 读取、显示和保存图像

在 OpenCV 中,图像的基本操作包括读取、显示和保存图像。这些操作是图像处理的基础。

读取图像 :使用imread函数读取图像。该函数的第一个参数是图像文件的路径,第二个参数是读取图像的方式(如彩色图像、灰度图像等)。

cpp 复制代码
cv::Mat image = cv::imread("image.jpg", cv::IMREAD_COLOR);

显示图像 :使用imshow函数显示图像。该函数的第一个参数是窗口的名称,第二个参数是要显示的图像。

cpp 复制代码
cv::imshow("Display Window", image);
cv::waitKey(0); // 等待按键按下

保存图像 :使用imwrite函数保存图像。该函数的第一个参数是保存文件的路径,第二个参数是要保存的图像。

cpp 复制代码
cv::imwrite("output.jpg", image);

1.2 图像的基本属性

图像的基本属性包括尺寸、通道数和像素值。

尺寸 :图像的尺寸可以通过rowscols属性获取。

cpp 复制代码
int height = image.rows;
int width = image.cols;

通道数 :图像的通道数可以通过channels()方法获取。

cpp 复制代码
int channels = image.channels();

像素值 :可以通过at方法访问图像的像素值。

cpp 复制代码
cv::Vec3b pixel = image.at<cv::Vec3b>(y, x); // 访问(x, y)处的像素值

1.3 图像的创建与初始化

可以通过Mat类创建和初始化图像。

创建图像:可以创建一个指定大小和类型的图像。

cpp 复制代码
cv::Mat newImage(480, 640, CV_8UC3, cv::Scalar(0, 0, 255)); // 创建一个640x480的红色图像

初始化图像 :可以使用setTo方法初始化图像。

cpp 复制代码
image.setTo(cv::Scalar(255, 255, 255)); // 将图像初始化为白色

1.4 图像的像素操作

图像的像素操作包括遍历像素和修改像素值。

遍历像素:可以使用双重循环遍历图像的每个像素。

cpp 复制代码
for (int y = 0; y < image.rows; y++) {
    for (int x = 0; x < image.cols; x++) {
        cv::Vec3b& pixel = image.at<cv::Vec3b>(y, x);
        // 对像素进行操作
    }
}

修改像素值:可以直接修改像素的值。

cpp 复制代码
pixel[0] = 255; // 将蓝色通道设置为255
pixel[1] = 0;   // 将绿色通道设置为0
pixel[2] = 0;   // 将红色通道设置为0

2. 图像的几何变换

2.1 缩放、旋转、平移、翻转

图像的几何变换包括缩放、旋转、平移和翻转。

缩放 :使用resize函数缩放图像。

cpp 复制代码
cv::Mat resizedImage;
cv::resize(image, resizedImage, cv::Size(newWidth, newHeight));

旋转 :使用getRotationMatrix2DwarpAffine函数旋转图像。

cpp 复制代码
cv::Point2f center(image.cols / 2.0, image.rows / 2.0);
cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, angle, 1.0);
cv::Mat rotatedImage;
cv::warpAffine(image, rotatedImage, rotationMatrix, image.size());

平移 :使用warpAffine函数平移图像。

cpp 复制代码
cv::Mat translationMatrix = (cv::Mat_<double>(2, 3) << 1, 0, tx, 0, 1, ty);
cv::Mat translatedImage;
cv::warpAffine(image, translatedImage, translationMatrix, image.size());

翻转 :使用flip函数翻转图像。

cpp 复制代码
cv::Mat flippedImage;
cv::flip(image, flippedImage, 1); // 1表示水平翻转,0表示垂直翻转

2.2 仿射变换与透视变换

仿射变换 :仿射变换是线性变换加上平移,可以使用warpAffine函数实现。

cpp 复制代码
cv::Mat affineMatrix = cv::getAffineTransform(srcPoints, dstPoints);
cv::Mat affineImage;
cv::warpAffine(image, affineImage, affineMatrix, image.size());

透视变换 :透视变换是更一般的变换,可以使用warpPerspective函数实现。

cpp 复制代码
cv::Mat perspectiveMatrix = cv::getPerspectiveTransform(srcPoints, dstPoints);
cv::Mat perspectiveImage;
cv::warpPerspective(image, perspectiveImage, perspectiveMatrix, image.size());

3.图像的颜色空间转换

3.1 RGB、灰度、HSV等颜色空间

图像的颜色空间包括RGB、灰度和HSV等。

  • RGB:RGB是最常见的颜色空间,表示红、绿、蓝三个通道。
  • 灰度:灰度图像只有一个通道,表示亮度。
  • HSV:HSV颜色空间表示色调(Hue)、饱和度(Saturation)和亮度(Value)。

3.2 颜色空间转换

使用 cvtColor 函数进行颜色空间转换。

RGB 转灰度

cpp 复制代码
cv::Mat grayImage;
cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);

RGB转HSV

cpp 复制代码
cv::Mat hsvImage;
cv::cvtColor(image, hsvImage, cv::COLOR_BGR2HSV);

3.3 通道分离与合并

通道分离 :使用split函数将图像的通道分离。

cpp 复制代码
std::vector<cv::Mat> channels;
cv::split(image, channels);

通道合并 :使用merge函数将多个通道合并为一个图像。

cpp 复制代码
cv::Mat mergedImage;
cv::merge(channels, mergedImage);

4. 实例

C++ OpenCV 的基础操作包括图像的读取、显示、保存、像素操作、图像属性获取等。以下是一些常见的 OpenCV 基础操作及其代码示例:

4.1 图像的读取与显示

cpp 复制代码
#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;
    }

    // 显示图像
    namedWindow("Display Image", WINDOW_AUTOSIZE);
    imshow("Display Image", image);

    // 等待按键
    waitKey(0);

    // 关闭窗口
    destroyAllWindows();

    return 0;
}

4.2 图像的保存

cpp 复制代码
#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;
    }

    // 保存图像
    bool isSaved = imwrite("saved_image.jpg", image);
    if (isSaved) {
        cout << "图像保存成功!" << endl;
    } else {
        cout << "图像保存失败!" << endl;
    }

    return 0;
}

4.3 获取图像属性

cpp 复制代码
#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;
    }

    // 获取图像属性
    int width = image.cols;  // 图像宽度
    int height = image.rows; // 图像高度
    int channels = image.channels(); // 图像通道数

    cout << "图像宽度: " << width << endl;
    cout << "图像高度: " << height << endl;
    cout << "图像通道数: " << channels << endl;

    return 0;
}

4.4 访问和修改像素值

cpp 复制代码
#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;
    }

    // 访问像素值(BGR格式)
    Vec3b pixel = image.at<Vec3b>(100, 100); // 获取(100, 100)位置的像素值
    cout << "B: " << (int)pixel[0] << ", G: " << (int)pixel[1] << ", R: " << (int)pixel[2] << endl;

    // 修改像素值
    image.at<Vec3b>(100, 100) = Vec3b(255, 0, 0); // 将(100, 100)位置的像素设置为蓝色

    // 显示修改后的图像
    imshow("Modified Image", image);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

4.5 图像颜色空间转换

cpp 复制代码
#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);

    // 显示灰度图像
    imshow("Gray Image", grayImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

4.6 图像的裁剪与缩放

cpp 复制代码
#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;
    }

    // 裁剪图像
    Rect roi(100, 100, 200, 200); // (x, y, width, height)
    Mat croppedImage = image(roi);

    // 缩放图像
    Mat resizedImage;
    resize(image, resizedImage, Size(400, 400)); // 缩放到400x400

    // 显示裁剪和缩放后的图像
    imshow("Cropped Image", croppedImage);
    imshow("Resized Image", resizedImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

4.7 图像的复制与克隆

cpp 复制代码
#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 copiedImage = image.clone();

    // 修改复制的图像
    circle(copiedImage, Point(100, 100), 50, Scalar(0, 255, 0), 2); // 在复制的图像上画一个圆

    // 显示原始图像和修改后的图像
    imshow("Original Image", image);
    imshow("Copied Image", copiedImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

4.8 图像的几何变换

cpp 复制代码
#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 rotatedImage;
    Point2f center(image.cols / 2, image.rows / 2); // 旋转中心
    double angle = 45; // 旋转角度
    double scale = 1.0; // 缩放比例
    Mat rotationMatrix = getRotationMatrix2D(center, angle, scale);
    warpAffine(image, rotatedImage, rotationMatrix, image.size());

    // 显示旋转后的图像
    imshow("Rotated Image", rotatedImage);
    waitKey(0);
    destroyAllWindows();

    return 0;
}

二、图像处理

1. 图像滤波

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

1.1 均值滤波

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

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

1.2 高斯滤波

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

cpp 复制代码
cv::GaussianBlur(src, dst, cv::Size(5, 5), 0);  // 5x5的高斯滤波

1.3 中值滤波

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

cpp 复制代码
cv::medianBlur(src, dst, 5);  // 5x5的中值滤波

1.4 自定义滤波器

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

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

2. 图像边缘检测

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

2.1 Sobel算子

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

cpp 复制代码
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);  // 合并结果

2.2 Canny 边缘检测

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

cpp 复制代码
cv::Canny(src, dst, 100, 200);  // 阈值1=100,阈值2=200

3. 图像形态学操作

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

3.1 腐蚀

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

cpp 复制代码
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
cv::erode(src, dst, kernel);

3.2 膨胀

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

cpp 复制代码
cv::dilate(src, dst, kernel);

3.3 开运算

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

cpp 复制代码
cv::morphologyEx(src, dst, cv::MORPH_OPEN, kernel);

3.4 闭运算

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

cpp 复制代码
cv::morphologyEx(src, dst, cv::MORPH_CLOSE, kernel);

形态学梯度

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

cpp 复制代码
cv::morphologyEx(src, dst, cv::MORPH_GRADIENT, kernel);

4. 图像阈值化

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

4.1 二值化

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

cpp 复制代码
cv::threshold(src, dst, 127, 255, cv::THRESH_BINARY);

4.2 自适应阈值

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

cpp 复制代码
cv::adaptiveThreshold(src, dst, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 11, 2);

4.3 Otsu阈值法

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

cpp 复制代码
cv::threshold(src, dst, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);

5. 图像直方图

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

5.1 计算直方图

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

cpp 复制代码
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);

5.2 直方图均衡化

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

cpp 复制代码
cv::equalizeHist(src, dst);

5.3 直方图对比

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

cpp 复制代码
double compare = cv::compareHist(hist1, hist2, cv::HISTCMP_CORREL);

6. 实例

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

6.1 图像滤波

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

均值滤波

cpp 复制代码
#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;
}

高斯滤波

cpp 复制代码
#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;
}

中值滤波

cpp 复制代码
#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;
}

6.2 边缘检测

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

Canny 边缘检测

cpp 复制代码
#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;
}

6.3 图像阈值化

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

简单阈值化

cpp 复制代码
#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;
}

自适应阈值化

cpp 复制代码
#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;
}

6.4 形态学操作

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

腐蚀与膨胀

cpp 复制代码
#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;
}

6.5 轮廓检测

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

cpp 复制代码
#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;
}
相关推荐
小李独爱秋2 小时前
【机器学习宝藏】深入解析经典人脸识别数据集:Olivetti Faces
人工智能·python·机器学习·计算机视觉·人脸识别·olivetti
程序猿小D6 小时前
【完整源码+数据集+部署教程】医疗设备显示器图像分割系统: yolov8-seg-C2f-SCConv
python·yolo·计算机视觉·数据集·yolov8·医疗设备显示器图像分割系统
蜀中廖化1 天前
Android Studio 导入 opencv
android·opencv·android studio
IT古董1 天前
【第五章:计算机视觉-项目实战之生成对抗网络实战】1.对抗生成网络原理-(1)对抗生成网络算法基础知识:基本思想、GAN的基本架构、应用场景、标注格式
人工智能·生成对抗网络·计算机视觉
浮生如梦_1 天前
图片转视频
图像处理·人工智能·计算机视觉·音视频
春末的南方城市1 天前
复旦&华为提出首个空间理解和生成统一框架UniUGG,支持参考图像和任意视图变换的 3D 场景生成和空间视觉问答 (VQA) 任务。
人工智能·科技·深度学习·计算机视觉·aigc
春末的南方城市1 天前
上交提出单图生成3D场景方法SceneGen:单图输入,多资源输出,3D 合成性能飙升的“秘密武器”!
人工智能·计算机视觉
天涯路s1 天前
OpenCV 基本模块
人工智能·opencv·计算机视觉
CV实验室2 天前
NeurIPS 2025 | 北大等提出C²Prompt:解耦类内与类间知识,攻克FCL遗忘难题!
人工智能·计算机视觉·prompt·论文·cv