/*
* 代码功能:手动选定初始边缘,使用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;}

Snake

鼠标左键画好轮廓后,S键控制轮廓收缩

版权声明:本文为gaohai原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/gaohai/p/5788850.html