31 OpenCV 距离变换和分水岭算法

devtools/2024/12/23 1:45:06/

文章目录

  • 距离变换
  • 分水岭算法
  • distanceTransform 距离变换
  • watershed 分水岭算法
  • 示例

距离变换

在这里插入图片描述

分水岭算法

在这里插入图片描述

distanceTransform 距离变换

void cv::distanceTransform (InputArray src,OutputArray dst,int distanceType,int maskSize,int dstType = CV_32F)
src:输入图像,数据类型为CV8U的单通道图像
dst:输出图像,与输入图像具有相同的尺寸,数据类型为CV_8U或者CV_32F的单通道图像distanceType:选择计算两个像素之间距离方法的标志, 常用的有DIST_L1、DIST_L2和DIST_C,分别表示街区距离、欧式距离和棋盘距离
maskSize: 距离变换掩码矩阵大小,可以选择尺寸为DIST_MASK_3(3×3)、DIST_MASK_ 5(5X5)
dstType:输出图像的数据类型,可以是CV_8U或者CV_32F

watershed 分水岭算法

void cv::watershed ( InputArray   image,InputOutputArray markers)
mage:输入图像,数据类型为CV_8U的三通道图像
markers:输入/输出CV_32S的单通道图像的标记结果,与原图像具有相同的尺寸

示例

示例流程
1.将白色背景变成黑色-目的是为后面的变换做准备
2. 使用filter2D与拉普拉斯算子实现图像对比度提高,sharp
3. 转为二值图像通过threshold
4. 距离变换
5. 对距离变换结果进行归一化到[0~1]之间
6. 使用阈值,再次二值化,得到标记
7. 腐蚀得到每个Peak - erode
8.发现轮廓 – findContours
9. 绘制轮廓- drawContours
10.分水岭变换 watershed
11. 对每个分割区域着色输出结果

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>using namespace std;
using namespace cv;int main(int argc, char** argv) {char input_win[] = "input image";char watershed_win[] = "watershed segmentation demo";Mat src = imread("D:/vcprojects/images/cards.png");// Mat src = imread("D:/kuaidi.jpg");if (src.empty()) {printf("could not load image...\n");return -1;}namedWindow(input_win, CV_WINDOW_AUTOSIZE);imshow(input_win, src);// 1. 将白色背景变成黑色-目的是为后面的变换做准备for (int row = 0; row < src.rows; row++) {for (int col = 0; col < src.cols; col++) {if (src.at<Vec3b>(row, col) == Vec3b(255, 255, 255)) {src.at<Vec3b>(row, col)[0] = 0;src.at<Vec3b>(row, col)[1] = 0;src.at<Vec3b>(row, col)[2] = 0;}}}namedWindow("black background", CV_WINDOW_AUTOSIZE);imshow("black background", src);//2.使用filter2D与拉普拉斯算子实现图像对比度提高,sharpMat kernel = (Mat_<float>(3, 3) << 1, 1, 1, 1, -8, 1, 1, 1, 1);Mat imgLaplance;Mat sharpenImg = src;filter2D(src, imgLaplance, CV_32F, kernel, Point(-1, -1), 0, BORDER_DEFAULT);src.convertTo(sharpenImg, CV_32F);Mat resultImg = sharpenImg - imgLaplance;resultImg.convertTo(resultImg, CV_8UC3);imgLaplance.convertTo(imgLaplance, CV_8UC3);imshow("sharpen image", resultImg);// src = resultImg; // copy back// 3. 转为二值图像通过thresholdMat binaryImg;cvtColor(src, resultImg, CV_BGR2GRAY);threshold(resultImg, binaryImg, 40, 255, THRESH_BINARY | THRESH_OTSU);imshow("binary image", binaryImg);//4. 距离变换Mat distImg;distanceTransform(binaryImg, distImg, DIST_L1, 3, 5);//5. 对距离变换结果进行归一化到[0~1]之间normalize(distImg, distImg, 0, 1, NORM_MINMAX);imshow("distance result", distImg);// 6. 使用阈值,再次二值化,得到标记threshold(distImg, distImg, .4, 1, THRESH_BINARY);Mat k1 = Mat::ones(13, 13, CV_8UC1);//7. 腐蚀得到每个Peak - erodeerode(distImg, distImg, k1, Point(-1, -1));imshow("distance binary image", distImg);//8.发现轮廓 – findContoursMat dist_8u;distImg.convertTo(dist_8u, CV_8U);vector<vector<Point>> contours;findContours(dist_8u, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));// 9. 绘制轮廓- drawContoursMat markers = Mat::zeros(src.size(), CV_32SC1);for (size_t i = 0; i < contours.size(); i++) {drawContours(markers, contours, static_cast<int>(i), Scalar::all(static_cast<int>(i) + 1), -1);}circle(markers, Point(5, 5), 3, Scalar(255, 255, 255), -1);imshow("my markers", markers*1000);//10.分水岭变换 watershedwatershed(src, markers);Mat mark = Mat::zeros(markers.size(), CV_8UC1);markers.convertTo(mark, CV_8UC1);bitwise_not(mark, mark, Mat());imshow("watershed image", mark);// generate random colorvector<Vec3b> colors;for (size_t i = 0; i < contours.size(); i++) {int r = theRNG().uniform(0, 255);int g = theRNG().uniform(0, 255);int b = theRNG().uniform(0, 255);colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));}// 11. 对每个分割区域着色输出结果Mat dst = Mat::zeros(markers.size(), CV_8UC3);for (int row = 0; row < markers.rows; row++) {for (int col = 0; col < markers.cols; col++) {int index = markers.at<int>(row, col);if (index > 0 && index <= static_cast<int>(contours.size())) {dst.at<Vec3b>(row, col) = colors[index - 1];}else {dst.at<Vec3b>(row, col) = Vec3b(0, 0, 0);}}}imshow("Final Result", dst);waitKey(0);return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


http://www.ppmy.cn/devtools/22658.html

相关文章

水稻病害检测(YOLO数据集,多分类,稻瘟病、纹枯病、褐斑病、枯心病、霜霉病、水稻细菌性条纹斑病、稻苞虫)

是自己利用LabelImg工具进行手工标注&#xff0c;数据集制作不易&#xff0c;请尊重版权&#xff08;稻瘟病、纹枯病、褐斑病、枯心病、霜霉病、水稻细菌性条纹斑病、稻苞虫&#xff09; 如果需要yolv8检测模型和数据集放在一起的压缩包&#xff0c;可以关注&#xff1a;最新最…

虚假新闻检测——Exploring the Role of Large Language Models in Fake News Detection

Bad Actor, Good Advisor: Exploring the Role of Large Language Models in Fake News Detection 论文地址: Bad Actor, Good Advisor: Exploring the Role of Large Language Models in Fake News Detection| Proceedings of the AAAI Conference on Artificial Intellige…

保证接口幂等性的多种实现方式(数据库方案)

1. 幂等性的概念 接口幂等性是指在软件工程和Web服务领域中&#xff0c;一个接口&#xff08;通常是HTTP API&#xff09;无论被调用一次还是多次&#xff0c;其对系统产生的副作用应该是相同的&#xff0c;即结果保持一致&#xff0c;不会因为多次请求而有所不同。换句话说&am…

【IDEA】设置Maven路径 当前项目 全部项目

IDEA设置Maven路径 1. 当前项目有效&#xff08;每次都要设置Maven路径&#xff09;2. 全部项目有效&#xff08;一次设置永久解决&#xff09; 1. 当前项目有效&#xff08;每次都要设置Maven路径&#xff09; 将Maven home path、User settings file、Local repository设置为…

抖音 通用交易系统 下单 密钥生成

已PHP为例 前提提条件 必须在 linux 系统中 生成 准备工作 在小程序中 生成应用公匙 把生成的公匙 复制 在linux 系统中 创建文件 private_key.pem 并将公匙粘贴 接下来打开命令 执行命令即可 openssl genrsa -out private_key.pem 2048 rsa -in private_key.pem -pubo…

SpringSecurity授权流程(自己做笔记用的)

目录 一、RABC表的设计 二、查询权限并添加Security中 三、通过注解进行授权 四、授权进行前端访问 一、RABC表的设计 基本概念就是五个表&#xff1a; 用户表&#xff1a;users 角色表&#xff1a;role 权限表&#xff1a;permission 还需要两种关系表&#xff0c;才能通过…

【喜报】科大睿智为武汉博睿英特科技高质量通过CMMI3级评估咨询工作

武汉博睿英特科技有限公司是信息通信技术产品、建筑智慧工程服务提供商。其拥有专注于航空、政府、教育、金融等多行业领域的资深团队&#xff0c;及时掌握最新信息通信应用技术&#xff0c;深刻理解行业业务流程&#xff0c;擅于整合市场优质资源&#xff0c;积极保持与高校产…

利用机器学习进行图像分类:以TensorFlow和Keras为例

当使用 TensorFlow 和 Keras 进行图像分类时&#xff0c;常用的方法是使用卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;。以下是一个简单的图像分类示例&#xff0c;使用 TensorFlow 和 Keras 来训练一个 CNN 模型对手写数字进行分类。 …