Opencv2.1中的图像切分grabcut实现

1.首先要先装上Opencv2.1,注意必须是2.1版本以上的,因为grabcut方法的实现只有在2.1开始才有实现好的函数可以使用。

2.还要装上c-make,用来编译Opencv2.1

以上两个步骤,请参考

http://www.opencv.org.cn/index.php/VC_2008_Express%E4%B8%8B%E5%AE%89%E8%A3%85OpenCV2.0/2.1

这里面非常详细的介绍了Opencv2.1的安装过程,必须注意,这里的编译器是Vs2008.

3在写程序前,要配置几项

 

打开VC++ 2008 Express,菜单 Tools -> Options -> Projects and Solutions -> VC++ Directories

  • Show directories for选择include files,加入目录 D:/Program Files/OpenCV2.0/vc2008/include/opencv
  • Show directories for选择library files,加入目录 D:/Program Files/OpenCV2.0/vc2008/lib

关闭VC++ 2008 Express。

点击看大图
点击看大图
[ 编辑 ]

使用OpenCV 2.1编程

  • 打开VC++ 2008 Express,创建一个空程序grabcut;
  • 选择Solution Explorer里的grabcut项目,点击鼠标右键,选择Properties;
  • 为项目的Debug配置增加依赖的库:cxcore210d.lib cv210d.lib highgui210d.lib
  • 为项目的Release配置增加依赖的库:cxcore210.lib cv210.lib highgui210.lib
  • 编译运行下面的例程(需要将lena.jpg文件放在项目目录下)。
  • 右键工程,点击下面的属性->配置属性->调试->命令参数->D:/图形/Grabcut/Grabcut/lena.jpg,输入图片放置的地方

 

#include <highgui.h> #include <cv.h> #include <iostream> using namespace std; using namespace cv; const string winName = "image"; const Scalar RED = Scalar(0,0,255); const Scalar BLUE = Scalar(255,0,0); Mat outImage; void getBinMask( const Mat& comMask, Mat& binMask ) //comMask 变换成binMask { if( comMask.empty() || comMask.type()!=CV_8UC1 ) CV_Error( CV_StsBadArg, "comMask is empty or has incorrect type (not CV_8UC1)" ); if( binMask.empty() || binMask.rows!=comMask.rows || binMask.cols!=comMask.cols ) binMask.create( comMask.size(), CV_8UC1 ); binMask = comMask & 1; } void changeMask( Mat& mask, vector<Point> bgdPixels, vector<Point> fgdPixels ) //把mask中的的前景背景改变 { vector<Point>::const_iterator it = bgdPixels.begin(), itEnd = bgdPixels.end(); for( ; it != itEnd; ++it ) mask.at<uchar>(*it) = GC_BGD; it = fgdPixels.begin(), itEnd = fgdPixels.end(); for( ; it != itEnd; ++it ) mask.at<uchar>(*it) = GC_FGD; } void showImage( Mat& _img, Mat& _mask, vector<Point>& _bgdPxls, vector<Point>& _fgdPxls ) //加载显示图像 { Mat res; Mat binMask; if( _mask.empty() ) //_mask为空,直接拷贝 _img.copyTo( res ); //_img -> res else //_mask不为空,变换后拷贝 { getBinMask( _mask, binMask ); //bin _img.copyTo( res, binMask ); //_img - binMask -> res 只拷贝binMask非空时_img的像素 } vector<Point>::const_iterator it; for( it = _bgdPxls.begin(); it != _bgdPxls.end(); ++it ) //画出背景信息 circle( res, *it, 1, BLUE ); //(图像,圆心坐标,圆心半径,颜色) // 函数cvCircle绘制或填充一个给定圆心和半径的圆。 //圆被感兴趣矩形所裁剪。 若指定圆的颜色,可以使用宏 CV_RGB ( r, g, b )。 for( it = _fgdPxls.begin(); it != _fgdPxls.end(); ++it ) //画出前景信息 circle( res, *it, 1, RED ); imshow( winName, res ); res.copyTo(outImage); } Mat image; Mat mask; Mat bgdModel, fgdModel; Rect rect; enum{ NOT_SET = 0, IN_PROCESS = 1, SET = 2 }; uchar rectState = NOT_SET; //矩形框 uchar lblsState = NOT_SET; vector<Point> fgdPxls, bgdPxls; Point p1, p2; int iterCount; /* 这个函数的原型应该为 void Foo(int event, int x, int y, int flags, void* param); 其中event是 CV_EVENT_*变量之一, x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系), flags是CV_EVENT_FLAG的组合, param是用户定义的传递到cvSetMouseCallback函数调用的参数。 */ void on_mouse( int event, int x, int y, int flags, void* param ) { switch( event ) { case CV_EVENT_LBUTTONDOWN: //单击鼠标左键down { bool isb = (flags & CV_EVENT_FLAG_ALTKEY) != 0, //是否选中alt键 isf = (flags & CV_EVENT_FLAG_SHIFTKEY) != 0; //是否选中shift键 if( rectState == NOT_SET && !isb && !isf ) //只点击左键时 { rectState = IN_PROCESS; //正在处理矩形框 p1 = Point(x, y); //起点 } if ( (isb || isf) && rectState == SET ) //选中alt或shift键,并且矩形框已设置 { lblsState = IN_PROCESS; //正在画背景或前景 } } break; case CV_EVENT_LBUTTONUP: //点击鼠标左键up if( rectState == IN_PROCESS ) //若是正在处理矩形框时 { p2 = Point(x, y); //终点 rect = Rect( p1, p2 ); //矩形框选中 rectState = SET; //矩形框状态为已设置 grabCut( image, mask, rect, bgdModel, fgdModel, 0, GC_INIT_WITH_RECT ); //grabCut 初始化 assert( bgdPxls.empty() && fgdPxls.empty() ); //判断背景和前景的画笔像素是否为空,为空报错 showImage( image, mask, bgdPxls, fgdPxls ); //刷新 } if( lblsState == IN_PROCESS ) //若是正在处理背景或前景画笔 { lblsState = NOT_SET; //画笔状态为0 showImage( image, mask, bgdPxls, fgdPxls ); //刷新 } break; case CV_EVENT_MOUSEMOVE: //鼠标移动 if( rectState == IN_PROCESS ) //若是正在处理矩形框时 { Mat res; image.copyTo(res); //image->res rectangle(res, p1, Point(x,y), Scalar(0,255,0), 2); //图像,矩形的一个顶点,矩形对角线上的另一个顶点,线条颜色,组成矩形的线条的粗细程度 imshow(winName, res); //显示鼠标移动时矩形框的变化 } else if( lblsState == IN_PROCESS ) //若是正在处理画笔 { Point p = Point(x, y); //当前点的坐标 if( flags & CV_EVENT_FLAG_ALTKEY ) //若是同时按键alt { bgdPxls.push_back(p); //背景画笔记录轨迹 showImage( image, mask, bgdPxls, fgdPxls ); //刷新显示轨迹 } if( flags & CV_EVENT_FLAG_SHIFTKEY ) //若是同时按键shift { fgdPxls.push_back( Point(x, y) ); //前景画笔记录轨迹 showImage( image, mask, bgdPxls, fgdPxls ); //刷新显示轨迹 } } break; } } int main( int argc, char** argv ) { if( argc==1 ) return 1; string filename = argv[1]; if( filename.empty() ) return 1; image = imread( filename, 1 ); if( image.empty() ) return 1; cout << "Hot keys: /n" << "/tESC - quit the program/n" "First, select the rectangular area/n" "/tr - restore the original image/n" "/tn - next iteration/n" "/n/n" "/tleft mouse button - set rectangle/n" "/talt+left mouse button - set background pixels/n" "/tshift+left mouse button - set foreground pixels/n"; cvNamedWindow( winName.c_str(), CV_WINDOW_AUTOSIZE ); //函数cvNamedWindow创建一个可以放置图像和trackbar的窗口。被创建的窗口可以通过它们的名字被引用。 imshow( winName, image ); //显示图像 cvSetMouseCallback( winName.c_str(), on_mouse, 0 ); //跟踪鼠标 //窗口名,指定窗口里每次鼠标事件发生的时候,被调用的函数指针,param是用户定义的传递到cvSetMouseCallback函数调用的参数。 //函数cvSetMouseCallback设定指定窗口鼠标事件发生时的回调函数 rectState = NOT_SET; lblsState = NOT_SET; iterCount = 0; for(;;) { int c = cvWaitKey(0); //等待输入 switch( (char) c ) { case '/x1b': //退出 cout << "Exiting ..." << endl; goto exit_main; case 'r': //重新加载图像 rectState = NOT_SET; lblsState = NOT_SET; iterCount = 0; bgdPxls.clear(); fgdPxls.clear(); mask.release(); cout << endl; assert( bgdPxls.empty() && fgdPxls.empty() && mask.empty() ); //检查是否为0,为0报错 showImage( image, mask, bgdPxls, fgdPxls ); //显示图像 break; case 'n': cout << "<" << iterCount << "... "; if( rectState == SET ) //框被选中 { changeMask( mask, bgdPxls, fgdPxls ); //改变蒙板 bgdPxls.clear(); fgdPxls.clear(); grabCut( image, mask, rect, bgdModel, fgdModel, 1 ); //执行grabCut算法 //grabCut( image, mask, rect, bgdModel, fgdModel, 0, GC_INIT_WITH_RECT ); //grabCut 初始化 showImage( image, mask, bgdPxls, fgdPxls ); //显示图像 cout << iterCount << ">" << endl; iterCount++; } else cout << "rect is not determined>" << endl; break; case 's': //保存图像 imwrite("save.jpg",outImage); cout <<"save..."<<endl; break; } } exit_main: cvDestroyWindow( winName.c_str() ); //释放窗口 return 0; } 

 

 

Opencv2.1中的图像切分grabcut实现_第1张图片

你可能感兴趣的:(String,properties,image,iterator,express,button)