求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 


业务架构设计
4月18-19日 在线直播



基于UML和EA进行系统分析设计
4月25-26日 北京+在线



AI 智能化软件测试方法与实践
5月23-24日 上海+在线
 
追随技术信仰

随时听讲座
每天看新闻
 
 
OpenCV 教程
1. OpenCV 简介
2. OpenCV 安装
3. OpenCV 安装(C++)
Python OpenCV
4. OpenCV 入门实例
5. OpenCV 基础模块
6. OpenCV 图像处理基础
7. OpenCV 图像基本操作
8. OpenCV 图像算术运算
9. OpenCV 图像阈值处理
10. OpenCV 图像平滑处理
11. OpenCV 图像形态学操作
12. OpenCV 图像边缘检测
13. OpenCV 图像轮廓检测
14. OpenCV 图像直方图
15. OpenCV 视频处理
16. OpenCV 视频目标跟踪
17. OpenCV 视频背景减除
18. OpenCV 人脸检测
19. OpenCV 物体识别
20. OpenCV 图像拼接
21. OpenCV 简单滤镜效果
C++ OpenCV
22. C++ OpenCV 基础操作
23. C++ OpenCV 图像处理
24. C++ OpenCV 基本模块介绍
25. C++ OpenCV 特征检测与描述
26. C++ OpenCV 高级图像处理
27. C++ OpenCV 视频处理
28. C++ OpenCV 机器学习与深度学习
29. C++ OpenCV 项目实战
30. C++ OpenCV 性能优化
 
 
目录
C++ OpenCV 高级图像处理
44 次浏览
4次  

高级图像处理是指在基础图像处理(如滤波、边缘检测等)的基础上,进一步实现更复杂的任务,例如图像分割、轮廓检测、形态学操作、直方图处理等。这些技术广泛应用于目标检测、图像分析、医学影像处理等领域。

高级图像处理的应用场景

医学影像分析:

  • 使用图像分割技术提取病变区域。

  • 使用形态学操作去除噪声。

目标检测与跟踪:

  • 使用轮廓检测和模板匹配定位目标。

  • 使用直方图处理增强目标特征。

图像增强:

  • 使用直方图均衡化提高图像对比度。

  • 使用分水岭算法分离重叠对象。

图像分割

图像分割是图像处理中的一个重要步骤,它将图像划分为多个区域或对象,以便于进一步的分析和处理。常见的图像分割方法包括基于阈值的分割、基于边缘的分割和基于区域的分割。

基于阈值的分割

基于阈值的分割是最简单的图像分割方法之一。它通过设定一个或多个阈值,将图像的像素值分为不同的类别。常见的阈值分割方法包括全局阈值和自适应阈值。

全局阈值分割

全局阈值分割使用一个固定的阈值将图像分为前景和背景。OpenCV 提供了 cv::threshold 函数来实现这一功能。

cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat dst;
cv::threshold(src, dst, 128, 255, cv::THRESH_BINARY);

以上代码中,128 是阈值,255 是最大像素值,cv::THRESH_BINARY 表示使用二值化方法。

自适应阈值分割

自适应阈值分割根据图像的局部区域动态调整阈值。OpenCV 提供了 cv::adaptiveThreshold 函数来实现这一功能。

cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat dst;
cv::adaptiveThreshold(src, dst, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 11, 2);

以上代码中,255 是最大像素值,cv::ADAPTIVE_THRESH_MEAN_C 表示使用局部均值作为阈值,11 是邻域大小,2 是常数。

基于边缘的分割

基于边缘的分割通过检测图像中的边缘来分割图像。常见的边缘检测算法包括 Canny 边缘检测和 Sobel 算子。

Canny 边缘检测

Canny 边缘检测是一种多阶段的边缘检测算法。OpenCV 提供了 cv::Canny 函数来实现这一功能。

cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat edges;
cv::Canny(src, edges, 100, 200);

以上代码中,100 和 200 是 Canny 算法的两个阈值。

基于区域的分割(分水岭算法)

基于区域的分割通过将图像划分为多个区域来实现分割。分水岭算法是一种常用的基于区域的分割方法。

分水岭算法

分水岭算法将图像视为地形图,通过模拟水流的扩散来分割图像。OpenCV 提供了 cv::watershed 函数来实现这一功能。

cv::Mat src = cv::imread("image.jpg");
cv::Mat markers = cv::Mat::zeros(src.size(), CV_32S);
cv::watershed(src, markers);

以上代码中,markers 是标记矩阵,用于存储分割结果。

轮廓检测

轮廓检测是图像处理中的一个重要步骤,它用于检测图像中的对象边界。OpenCV 提供了多种轮廓检测和处理的函数。

查找轮廓

查找轮廓是轮廓检测的第一步。OpenCV 提供了 cv::findContours 函数来实现这一功能。

cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(src, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);

以上代码中,contours 是存储轮廓的向量,hierarchy 是存储轮廓层次结构的向量。

轮廓特征

轮廓特征包括面积、周长、边界框等。OpenCV 提供了多种函数来计算这些特征。

面积

面积是轮廓的一个重要特征。OpenCV 提供了 cv::contourArea 函数来计算轮廓的面积。

double area = cv::contourArea(contours[0]);

周长

周长是轮廓的另一个重要特征。OpenCV 提供了 cv::arcLength 函数来计算轮廓的周长。

double perimeter = cv::arcLength(contours[0], true);

边界框

边界框是轮廓的最小外接矩形。OpenCV 提供了 cv::boundingRect 函数来计算边界框。

cv::Rect rect = cv::boundingRect(contours[0]);

轮廓绘制

轮廓绘制是将检测到的轮廓绘制到图像上。OpenCV 提供了 cv::drawContours 函数来实现这一功能。

cv::Mat dst = cv::Mat::zeros(src.size(), CV_8UC3);
cv::drawContours(dst, contours, -1, cv::Scalar(0, 255, 0), 2);

以上代码中,dst 是绘制轮廓后的图像,cv::Scalar(0, 255, 0) 是轮廓的颜色,2 是轮廓的线宽。

模板匹配

模板匹配是一种在图像中查找特定模板的方法。OpenCV 提供了 cv::matchTemplate 函数来实现这一功能。

单模板匹配

单模板匹配是在图像中查找一个模板。OpenCV 提供了 cv::matchTemplate 函数来实现这一功能。

cv::Mat src = cv::imread("image.jpg");
cv::Mat templ = cv::imread("template.jpg");
cv::Mat result;
cv::matchTemplate(src, templ, result, cv::TM_CCOEFF_NORMED);

以上代码中,result 是匹配结果矩阵,cv::TM_CCOEFF_NORMED 是匹配方法。

多模板匹配

多模板匹配是在图像中查找多个模板。可以通过遍历匹配结果矩阵来实现多模板匹配。

double minVal, maxVal;
cv::Point minLoc, maxLoc;
cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);

以上代码中,maxLoc 是匹配结果的最大值位置。

实例

分水岭算法

实例

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

using namespace cv;
using namespace std;

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

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

    // 二值化
    Mat binary;
    threshold(gray, binary, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);

    // 去除噪声
    Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
    morphologyEx(binary, binary, MORPH_OPEN, kernel, Point(-1, -1), 2);

    // 计算距离变换
    Mat dist;
    distanceTransform(binary, dist, DIST_L2, 5);

    // 归一化距离变换图像
    normalize(dist, dist, 0, 1.0, NORM_MINMAX);

    // 二值化距离变换图像
    threshold(dist, dist, 0.5, 1.0, THRESH_BINARY);

    // 查找轮廓
    Mat dist_8u;
    dist.convertTo(dist_8u, CV_8U);
    vector<vector<Point>> contours;
    findContours(dist_8u, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    // 创建标记图像
    Mat markers = Mat::zeros(dist.size(), CV_32S);
    for (size_t i = 0; i < contours.size(); i++) {
        drawContours(markers, contours, static_cast<int>(i), Scalar(static_cast<int>(i) + 1), -1);
    }

    // 应用分水岭算法
    watershed(image, markers);

    // 显示结果
    Mat result = image.clone();
    for (int i = 0; i < markers.rows; i++) {
        for (int j = 0; j < markers.cols; j++) {
            if (markers.at<int>(i, j) == -1) {
                result.at<Vec3b>(i, j) = Vec3b(0, 255, 0); // 标记边界为绿色
            }
        }
    }

    imshow("Watershed Result", result);
    waitKey(0);

    return 0;
}

轮廓检测

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

OpenCV 提供了 findContours 函数来检测轮廓。

实例

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

using namespace cv;
using namespace std;

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

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

    // 二值化
    Mat binary;
    threshold(gray, binary, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);

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

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

    // 显示结果
    imshow("Contours", result);
    waitKey(0);

    return 0;
}

形态学操作

形态学操作是基于形状的图像处理技术,常用于去除噪声、分离对象等。

实例

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

using namespace cv;
using namespace std;

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

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

    // 二值化
    Mat binary;
    threshold(gray, binary, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);

    // 定义核
    Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));

    // 开运算(去除噪声)
    Mat opened;
    morphologyEx(binary, opened, MORPH_OPEN, kernel);

    // 闭运算(填充孔洞)
    Mat closed;
    morphologyEx(opened, closed, MORPH_CLOSE, kernel);

    // 显示结果
    imshow("Original Binary", binary);
    imshow("Opened Image", opened);
    imshow("Closed Image", closed);
    waitKey(0);

    return 0;
}

直方图处理

直方图处理用于分析图像的像素分布,常见的操作包括直方图均衡化、直方图匹配等。

实例

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

using namespace cv;
using namespace std;

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

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

    // 直方图均衡化
    Mat equalized;
    equalizeHist(gray, equalized);

    // 显示结果
    imshow("Original Image", gray);
    imshow("Equalized Image", equalized);
    waitKey(0);

    return 0;
}

模板匹配

模板匹配用于在图像中查找与模板相似的区域。

实例


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

using namespace cv;
using namespace std;

int main() {
    // 读取图像和模板
    Mat image = imread("scene.jpg");
    Mat templ = imread("template.jpg");
    if (image.empty() || templ.empty()) {
        cout << "错误:无法加载图像,请检查路径是否正确。" << endl;
        return -1;
    }

    // 模板匹配
    Mat result;
    matchTemplate(image, templ, result, TM_CCOEFF_NORMED);

    // 找到最佳匹配位置
    double minVal, maxVal;
    Point minLoc, maxLoc;
    minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);

    // 绘制矩形框
    rectangle(image, maxLoc, Point(maxLoc.x + templ.cols, maxLoc.y + templ.rows), Scalar(0, 255, 0), 2);

    // 显示结果
    imshow("Template Matching", image);
    waitKey(0);

    return 0;
}

您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码: 验证码,看不清楚?请点击刷新验证码 必填



44 次浏览
4次