5.5用分水岭算法实现图像分割

来源:互联网 发布:apache kylin api文档 编辑:程序博客网 时间:2024/05/16 10:02
<img src="http://img.blog.csdn.net/20160409220852681?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />直接上代码吧,还不是太理解
//watershedSegmentation.h#if !defined WATERSHS#define WATERSHS#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>class WatershedSegmenter {<img src="http://img.blog.csdn.net/20160409220658944?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /><img src="http://img.blog.csdn.net/20160409220658944?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />private:cv::Mat markers;public:void setMarkers(const cv::Mat& markerImage) {// Convert to image of intsmarkerImage.convertTo(markers,CV_32S);}cv::Mat process(const cv::Mat &image) {// Apply watershedcv::watershed(image,markers);return markers;}// Return result in the form of an imagecv::Mat getSegmentation() {cv::Mat tmp;// all segment with label higher than 255// will be assigned value 255markers.convertTo(tmp,CV_8U);return tmp;}// Return watershed in the form of an imagecv::Mat getWatersheds() {cv::Mat tmp;markers.convertTo(tmp,CV_8U,255,255);return tmp;}};#endif//
//main
#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include "watershedSegmentation.h"int main(){#if 1// Read input imagecv::Mat image= cv::imread("C:\\Users\\Administrator\\Desktop\\工作\\testp\\group.jpg");if (!image.data)return 0; // Display the imagecv::namedWindow("Original Image");cv::imshow("Original Image",image);// Get the binary mapcv::Mat binary;binary= cv::imread("C:\\Users\\Administrator\\Desktop\\工作\\testp\\binary.bmp",0);// Display the binary imagecv::namedWindow("Binary Image");cv::imshow("Binary Image",binary);// Eliminate noise and smaller objectscv::Mat fg;cv::erode(binary,fg,cv::Mat(),cv::Point(-1,-1),6);// Display the foreground imagecv::namedWindow("Foreground Image");cv::imshow("Foreground Image",fg);cv::imwrite("ForegroundImage.jpg",fg);// Identify image pixels without objectscv::Mat bg;cv::dilate(binary,bg,cv::Mat(),cv::Point(-1,-1),6);cv::threshold(bg,bg,1,128,cv::THRESH_BINARY_INV);// Display the background imagecv::namedWindow("Background Image");cv::imshow("Background Image",bg);//cv::imwrite("BackgroundImage.jpg",bg);// Show markers imagecv::Mat markers(binary.size(),CV_8U,cv::Scalar(0));markers= fg+bg;cv::namedWindow("Markers");cv::imshow("Markers",markers);//cv::imwrite("Markers.jpg",markers);// Create watershed segmentation objectWatershedSegmenter segmenter;// Set markers and processsegmenter.setMarkers(markers);segmenter.process(image);//imshow("11",markers);// Display segmentation resultcv::namedWindow("Segmentation");cv::imshow("Segmentation",segmenter.getSegmentation());//cv::imwrite("Segmentation.jpg",segmenter.getSegmentation());// Display watershedscv::namedWindow("Watersheds");cv::imshow("Watersheds",segmenter.getWatersheds());//cv::imwrite("Watersheds.jpg",segmenter.getWatersheds());#endif#if 1// Open another image image= cv::imread("C:\\Users\\Administrator\\Desktop\\工作\\testp\\tower.jpg");// Identify background pixelscv::Mat imageMask(image.size(),CV_8U,cv::Scalar(0));cv::rectangle(imageMask,cv::Point(5,5),cv::Point(image.cols-5,image.rows-5),cv::Scalar(255),3);// Identify foreground pixels (in the middle of the image)cv::rectangle(imageMask,cv::Point(image.cols/2-10,image.rows/2-10),cv::Point(image.cols/2+10,image.rows/2+10),cv::Scalar(1),10);// Set markers and processsegmenter.setMarkers(imageMask);//imshow("mask+rectangle",imageMask);segmenter.process(image);//imshow("seg_prosswater",segmenter.process(image));// Display the image with markerscv::rectangle(image,cv::Point(5,5),cv::Point(image.cols-5,image.rows-5),cv::Scalar(255,255,255),3);cv::rectangle(image,cv::Point(image.cols/2-10,image.rows/2-10),cv::Point(image.cols/2+10,image.rows/2+10),cv::Scalar(1,1,1),10);cv::namedWindow("Image with marker");cv::imshow("Image with marker",image);//cv::imwrite("Image with marker.jpg",image);// Display watershedscv::namedWindow("Watersheds of foreground object");cv::imshow("Watersheds of foreground object",segmenter.getWatersheds());//cv::imwrite("Watersheds of foreground object.jpg",segmenter.getWatersheds());#endifcv::waitKey();return 0;} <pre code_snippet_id="1640334" snippet_file_name="blog_20160409_7_2417268" name="code" class="cpp"></pre><pre code_snippet_id="1640334" snippet_file_name="blog_20160409_8_847105" name="code" class="cpp">不是太理解,标记图像第一副图像是前景和背景,但是后面一副图像直接是2个矩形。。反正经过处理之后图像的边缘像素值为-1


下面是opencv3的代码 来自毛星云

//--------------------------------------【程序说明】-------------------------------------------//程序说明:《OpenCV3编程入门》OpenCV2版书本配套示例程序77//程序描述:分水岭算法综合示例//开发测试所用操作系统: Windows 7 64bit//开发测试所用IDE版本:Visual Studio 2010//开发测试所用OpenCV版本:2.4.9//2014年06月 Created by @浅墨_毛星云//2014年11月 Revised by @浅墨_毛星云//------------------------------------------------------------------------------------------------//---------------------------------【头文件、命名空间包含部分】----------------------------//描述:包含程序所使用的头文件和命名空间//------------------------------------------------------------------------------------------------#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <iostream>using namespace cv;using namespace std;//-----------------------------------【宏定义部分】-------------------------------------------- //  描述:定义一些辅助宏 //------------------------------------------------------------------------------------------------ #define WINDOW_NAME1 "【程序窗口1】"        //为窗口标题定义的宏 #define WINDOW_NAME2 "【分水岭算法效果图】"        //为窗口标题定义的宏//-----------------------------------【全局函变量声明部分】--------------------------------------//描述:全局变量的声明//-----------------------------------------------------------------------------------------------Mat g_maskImage, g_srcImage;Point prevPt(-1, -1);//-----------------------------------【全局函数声明部分】--------------------------------------//描述:全局函数的声明//-----------------------------------------------------------------------------------------------static void ShowHelpText();static void on_Mouse( int event, int x, int y, int flags, void* );//-----------------------------------【main( )函数】--------------------------------------------//描述:控制台应用程序的入口函数,我们的程序从这里开始执行//-----------------------------------------------------------------------------------------------int main( int argc, char** argv ){//【0】改变console字体颜色system("color 6F"); //【0】显示帮助文字ShowHelpText( );//【1】载入原图并显示,初始化掩膜和灰度图g_srcImage = imread("1.jpg", 1);imshow( WINDOW_NAME1, g_srcImage );Mat srcImage,grayImage;g_srcImage.copyTo(srcImage);cvtColor(g_srcImage, g_maskImage, COLOR_BGR2GRAY);cvtColor(g_maskImage, grayImage, COLOR_GRAY2BGR);g_maskImage = Scalar::all(0);//【2】设置鼠标回调函数setMouseCallback( WINDOW_NAME1, on_Mouse, 0 );//【3】轮询按键,进行处理while(1){//获取键值int c = waitKey(0);//若按键键值为ESC时,退出if( (char)c == 27 )break;//按键键值为2时,恢复源图if( (char)c == '2' ){g_maskImage = Scalar::all(0);srcImage.copyTo(g_srcImage);imshow( "image", g_srcImage );}//若检测到按键值为1或者空格,则进行处理if( (char)c == '1' || (char)c == ' ' ){//定义一些参数int i, j, compCount = 0;vector<vector<Point> > contours;vector<Vec4i> hierarchy;//寻找轮廓findContours(g_maskImage, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);//轮廓为空时的处理if( contours.empty() )continue;//拷贝掩膜Mat maskImage(g_maskImage.size(), CV_32S);maskImage = Scalar::all(0);//循环绘制出轮廓    //感觉这里绘制轮廓不重要,重要的是几个 因为后面又覆盖了maskImage watershed( srcImage, maskImage );for( int index = 0; index >= 0; index = hierarchy[index][0], compCount++ )drawContours(maskImage, contours, index, Scalar::all(compCount+1), -1, 8, hierarchy, INT_MAX);//compCount为零时的处理if( compCount == 0 )continue;//生成随机颜色vector<Vec3b> colorTab;for( i = 0; i < compCount; i++ ){int b = theRNG().uniform(0, 255);int g = theRNG().uniform(0, 255);int r = theRNG().uniform(0, 255);colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));}//计算处理时间并输出到窗口中double dTime = (double)getTickCount();watershed( srcImage, maskImage );dTime = (double)getTickCount() - dTime;printf( "\t处理时间 = %gms\n", dTime*1000./getTickFrequency() );//双层循环,将分水岭图像遍历存入watershedImage中Mat watershedImage(maskImage.size(), CV_8UC3);for( i = 0; i < maskImage.rows; i++ )for( j = 0; j < maskImage.cols; j++ ){int index = maskImage.at<int>(i,j);           //不同的index用不同的index颜色if( index == -1 )watershedImage.at<Vec3b>(i,j) = Vec3b(255,255,255);else if( index <= 0 || index > compCount )watershedImage.at<Vec3b>(i,j) = Vec3b(0,0,0);elsewatershedImage.at<Vec3b>(i,j) = colorTab[index - 1];}//混合灰度图和分水岭效果图并显示最终的窗口watershedImage = watershedImage*0.5 + grayImage*0.5;imshow( WINDOW_NAME2, watershedImage );}}return 0;}//-----------------------------------【onMouse( )函数】---------------------------------------//描述:鼠标消息回调函数//-----------------------------------------------------------------------------------------------static void on_Mouse( int event, int x, int y, int flags, void* ){//处理鼠标不在窗口中的情况if( x < 0 || x >= g_srcImage.cols || y < 0 || y >= g_srcImage.rows )return;//处理鼠标左键相关消息if( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )prevPt = Point(-1,-1);else if( event == CV_EVENT_LBUTTONDOWN )prevPt = Point(x,y);//鼠标左键按下并移动,绘制出白色线条else if( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON) ){Point pt(x, y);if( prevPt.x < 0 )prevPt = pt;line( g_maskImage, prevPt, pt, Scalar::all(255), 5, 8, 0 );line( g_srcImage, prevPt, pt, Scalar::all(0), 5, 8, 0 );prevPt = pt;imshow(WINDOW_NAME1, g_srcImage);}}//-----------------------------------【ShowHelpText( )函数】----------------------------------  //      描述:输出一些帮助信息  //----------------------------------------------------------------------------------------------  static void ShowHelpText()  {  //输出欢迎信息和OpenCV版本printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");printf("\n\n\t\t\t此为本书OpenCV2版的第77个配套示例程序\n");printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION );printf("\n\n  ----------------------------------------------------------------------------\n");//输出一些帮助信息  printf(  "\n\n\n\t欢迎来到【分水岭算法】示例程序~\n\n");  printf(  "\t请先用鼠标在图片窗口中标记出大致的区域,\n\n\t然后再按键【1】或者【SPACE】启动算法。""\n\n\t按键操作说明: \n\n"  "\t\t键盘按键【1】或者【SPACE】- 运行的分水岭分割算法\n"  "\t\t键盘按键【2】- 恢复原始图片\n"  "\t\t键盘按键【ESC】- 退出程序\n\n\n");  }  


                                             
1 0
原创粉丝点击