opencv3实现分水岭算法-watershed函数
2015-10-20 00:13
369 查看
#include<iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv; bool g_bDrawing = false; Point g_CurrPoint, g_OrgPoint; int g_nThick = 5, g_nBlue = 255, g_nGreen = 255, g_nRed = 0; int g_nImageOneValue = 49; Mat srcImage; Mat grayImage; Mat maskImage; /*注意:不能在毁掉函数中写入未初始化的矩阵类,所以需要用时,需要写一个标志位,然后再在while(1)循环内使用*/ void onMouse(int event, int x, int y, int flag, void *param) { Mat &img = *(cv::Mat*)param; switch (event) { //移动鼠标的时候 case CV_EVENT_MOUSEMOVE: { g_OrgPoint = g_CurrPoint; g_CurrPoint = Point(x, y); if (g_bDrawing == 1) { line(srcImage, g_CurrPoint, g_OrgPoint, Scalar(g_nBlue, g_nGreen, g_nRed), g_nThick); imshow("【鼠标事件窗口】", srcImage); //在掩码图上进行显示 line(maskImage, g_CurrPoint, g_OrgPoint, Scalar(g_nBlue, g_nGreen, g_nRed), g_nThick); imshow("【掩码图像】", maskImage); } } break; //点击鼠标左键时 case CV_EVENT_LBUTTONDOWN: { g_bDrawing = true; g_OrgPoint = Point(x, y); g_CurrPoint = g_OrgPoint; } break; //松开鼠标左键时 case CV_EVENT_LBUTTONUP: { g_bDrawing = false; } break; } } int main() { Mat tempImage; RNG &rng = theRNG(); srcImage = imread("2.jpg"); //用一个变量来存储原图像 Mat g_srcImage; srcImage.copyTo(g_srcImage); //为掩码图 分配空间 //因为后面需要在掩码图像中寻找轮廓,所以需要一幅单通道的图像 maskImage.create(srcImage.size(), CV_8UC1); maskImage = Scalar::all(0); //需要得到一个 三个通道的灰度图, 以便之后在该灰度图中画上彩色,便于看清效果 //首先将原图灰度化,再将灰度化的图转换到 bgr空间中 cvtColor(srcImage, tempImage, CV_BGR2GRAY); cvtColor(tempImage, grayImage, CV_GRAY2BGR); namedWindow("【鼠标事件窗口】"); setMouseCallback("【鼠标事件窗口】", onMouse, 0); namedWindow("【滚动条窗口】", 0); createTrackbar("thick", "【滚动条窗口】", &g_nThick, 100, 0); createTrackbar("Blue", "【滚动条窗口】", &g_nBlue, 255, 0); createTrackbar("Green", "【滚动条窗口】", &g_nGreen, 255, 0); createTrackbar("Red", "【滚动条窗口】", &g_nRed, 255, 0); createTrackbar("Value", "【滚动条窗口】", &g_nImageOneValue, 100, 0); char key; while (1) { imshow("【鼠标事件窗口】", srcImage); key = waitKey(); if (key == 27) break; //如果检测到 键值是1 则恢复原图 if (key == '1') { g_srcImage.copyTo(srcImage); maskImage = Scalar::all(0); imshow("【鼠标事件窗口】", srcImage); } //如果检测到空格 则开始执行分水岭算法 if (key == ' ') { //分水岭算法的步骤: /*1、首先在掩码图中找到轮廓, 目的是让区域有索引值 2、用索引值来替代轮廓所包围的所有像素,使在一个轮廓中的像素,具有相同的像素值 3、利用分水岭算法函数将 区域内的像素值用索引值来代替 4、遍历得到的图像,使具有相同像素值的元素得到同一种颜色,方便显示(这一步 是使之前不易显示的图像得到显示)*/ //首先,在掩码图像中寻找轮廓 vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(maskImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE); //利用分水岭算法函数 //因为该函数的输出的图像和输入的图像是一个类型的,所以需要借助中间变量,同时也要保证中间变量具有索引值 //这就可以通过在中间变变量中绘制轮廓来实现对轮廓索引值的标注 Mat midImage(maskImage.size(), CV_32S, Scalar(0)); for (int i = 0; i < (int)contours.size(); i++) { //让每个像素都得到标记 drawContours(midImage, contours, i, Scalar(i + 1), -1/*填充*/, 8, hierarchy); } imshow("【绘制轮廓的图】", midImage); //分水岭算法的实现 //函数中的midImage已经为图像的每个像素储存了索引值,就利用这些索引值对原图像进行分水岭操作 //以标记作为基准,利用分水岭算法进行扩展 watershed(g_srcImage, midImage); //显示分水岭算法后的图像 imshow("【分水岭算法结果图】", midImage); //遍历得到的掩码图像,用颜色值来替代相同的索引值 //在这之前需要先定义一个随机颜色 vector<Vec3b> rngColor((int)contours.size()); rngColor.clear(); for (int i = 0; i < (int)contours.size(); i++) { uchar blue = rng.uniform(0, 255); uchar green = rng.uniform(0, 255); uchar red = rng.uniform(0, 255); rngColor.push_back(Vec3b(blue, green, red)); } //开始绘制 Mat waterImage(srcImage.size(), CV_8UC3); for (int i = 0; i < midImage.rows; i++) { for (int j = 0; j < midImage.cols; j++) { int g_nValue = midImage.at<int>(i, j); if (g_nValue == -1) waterImage.at<Vec3b>(i, j) = Vec3b(255, 255, 255); else if (g_nValue == 0) waterImage.at<Vec3b>(i, j) = Vec3b(0, 0, 0); else waterImage.at<Vec3b>(i, j) = rngColor[g_nValue - 1]; } } waterImage = waterImage * ((1 + g_nImageOneValue) / 100.0) + grayImage * (1 - ((1 + g_nImageOneValue) / 100.0)); imshow("【分水岭图像】", waterImage); } } return 0; }
相关文章推荐
- opencv3矩的计算-在图像中的应用-滚动条
- opencv3矩的计算-在图像中的应用
- Linux之split命令详解
- 表单提交错误后返回内容消失问题的解决方法(PHP网站)
- CXF+Spring+Tomcat简明示例
- AOP的半自动代理 及 缺点
- Linux常见的挂载目录说明
- Linux中mysql忘记密码,或者登录不上,等等,都可使用以下方式
- Linux安装软件
- svnserve.conf: Option expected的问题解决方法
- nginx整合tomcat实现域名泛解析
- linux 开机自动清空/tmp目录是怎么回事
- linux下安装7z命令及7z命令的使用
- tomcat问题总结
- 设置Hadoop+Hbase集群pid文件存储位置
- Servlet学习笔记--统计网站的访问量(jsp/servlet)
- CentOS编译安装LAMP
- 学习日志---linux 磁盘分区的挂载
- Centos6.3 Minimal 虚拟机安装与配置
- Hadoop(七)——子项目Hive