/* * 代码功能:手动选定初始边缘,使用cvSnakeImage算法迭代寻优 * 修改:jink2005 2009-11-18 * 论坛:http://www.aiseminar.cn/bbs */ #include "cv.h" #include "highgui.h" #include <iostream> #include <vector> #include <opencv2/legacy/legacy.hpp> //#pragma comment(lib, "highgui.lib") //#pragma comment(lib, "cv.lib") //#pragma comment(lib, "cvaux.lib") //#pragma comment(lib, "cxcore.lib") std::vector<CvPoint> InitContour; IplImage* temp; //= cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1); /* * 使用直线连接轮廓点,绘制轮廓线的函数 */ void showContent(IplImage * img) { if(temp == NULL) temp = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1); cvCopyImage(img, temp); for (int i = 0; i < InitContour.size(); i++) { cvCircle(temp, InitContour[i], 2, cvScalarAll(155)); if(i > 0) cvLine(temp, InitContour[i-1], InitContour[i], cvScalarAll(100), 1); } cvShowImage("srcImage", temp); } void on_mouse(int event, int x, int y, int flags, void* ptr) { if(event == CV_EVENT_LBUTTONDOWN) { InitContour.push_back(cvPoint(x,y)); /*InitContour.push_back(cvPoint(130,130)); for(int i=130;i<660;i=i+10) { InitContour.push_back(cvPoint(i,130)); } for(int i=130;i<660;i=i+20) { InitContour.push_back(cvPoint(660,i)); } for(int i=660;i>130;i=i-10) { InitContour.push_back(cvPoint(i,660)); } for(int i=660;i>130;i=i-20) { InitContour.push_back(cvPoint(130,i)); } InitContour.push_back(cvPoint(130,130));*/ showContent((IplImage *)ptr); } } int main(int argc, char* argv[]) { IplImage * srcimage = NULL; if (argc == 2 && (srcimage = cvLoadImage((char *)argv[1], CV_LOAD_IMAGE_GRAYSCALE)) !=0) ; else //载入工作目录下文件名为apple.jpg的图片。 { srcimage = cvLoadImage("test1.jpg", CV_LOAD_IMAGE_GRAYSCALE); } if(srcimage == NULL) { std::cout << "Can't find the image file!" << std::endl; return -1; } InitContour.clear(); cvNamedWindow("srcImage"); cvShowImage("srcImage", srcimage); cvSetMouseCallback("srcImage", on_mouse, srcimage); char c; while(char c = cvWaitKey(0)) if(c == 's' || c == 'S') break; // 设置snake算法使用的参数 float alpha = 1.0; float beta = 0.5; float gamma = 1.0; CvSize size; size.width = 3; size.height = 3; CvTermCriteria criteria; criteria.type = CV_TERMCRIT_ITER; criteria.max_iter = 500; criteria.epsilon = 0.1; int itetime = 100; for(int ite = 0; ite < itetime; ite++) // cvSnakeImage自己有循环,为什么这里还要?手动控制循环次数! { CvPoint* pts = new CvPoint[InitContour.size()]; for (int i = 0; i < InitContour.size(); i++) { pts[i] = InitContour[i]; } // 使用snake算法来修改轮廓 cvSnakeImage(srcimage, pts, InitContour.size(), &alpha, &beta, &gamma, CV_VALUE, size, criteria, 1); int size = InitContour.size(); // 清空原轮廓,更新为新的轮廓点 InitContour.clear(); for (int i = 0; i < size; i++) { InitContour.push_back(pts[i]); // 对轮廓点进行线性插值,插入中间点 int next = (i + 1) % size; CvPoint ne = pts[next]; if(size < 100) { CvPoint mid = cvPoint((pts[i].x + ne.x) / 2, (pts[i].y + ne.y) / 2); InitContour.push_back(mid); } } delete []pts; showContent(srcimage); cvWaitKey(); // 手动控制增加迭代次数,按任意键 } showContent(srcimage); cvWaitKey(); return 0;}
鼠标左键画好轮廓后,S键控制轮廓收缩