首页 > 技术文章 > OpenCV 鼠标手动绘制掩码图像

aobosir 2016-07-04 03:54 原文

OpenCV 鼠标手动绘制掩码图像

完整的代码:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include <stdio.h>  
#include <stdlib.h>  
#include <iostream>  
using namespace std;  
using namespace cv;  


cv::Mat  marker_mask;  
cv::Mat markers;  
cv::Mat img0, img, img_gray, wshed;  
cv::Point prev_pt(-1,-1);  

void on_mouse( int event, int x, int y, int flags, void* param )  
{  
    if( !img.data )  
        return;  

    if( event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON) )  
        prev_pt = cv::Point(-1,-1);  
    else if( event == CV_EVENT_LBUTTONDOWN )  
        prev_pt = cv::Point(x,y);  
    else if( event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON) )  
    {  
        cv::Point pt(x,y);  
        if( prev_pt.x < 0 )  
            prev_pt = pt;  
        cv::line( marker_mask, prev_pt, pt, cv::Scalar::all(255), 1, 8, 0 );  
        cv::line( img, prev_pt, pt, cv::Scalar::all(255), 1, 8, 0 );  
        prev_pt = pt;  
        cv::imshow( "image", img );  
    }  
}  

int main(){
    img0 = cv::imread("phase_map_org.bmp", 1);
    if(!img0.data)  
        return 0;  

    cv::namedWindow( "image" );  
    cv::namedWindow( "watershed transform" );  

    img = img0.clone();  
    img_gray = img0.clone();  
    wshed = img0.clone();  
    marker_mask = cv::Mat( img.size(), CV_8U, cv::Scalar::all(0));  

    cv::imshow( "image", img );  
    cv::imshow( "watershed transform", wshed );  
    cvSetMouseCallback( "image", on_mouse, 0 );  

    for(;;){  
        int c = cv::waitKey(0);  

        if( (char)c == 27 )  
            break;  

        if( (char)c == 'r' )  {  
            marker_mask.setTo(cv::Scalar::all(0));  
            img0.copyTo(img);  
            cv::imshow( "image", img );  
        }  
        if( (char)c == 's' )  {
            cv::imwrite("marker_mask.bmp", marker_mask);
            std::cout << "save marker_mask.bmp finals " << std::endl;
        }
        if( (char)c == 'p' )  {
            std::cout << "processing ... " << std::endl;
            std::vector<std::vector<cv::Point> > contours;
            vector<Vec4i> hierarchy;
            cv::findContours( marker_mask, contours, 
                            CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );  

            marker_mask.setTo(cv::Scalar::all(0));  
            cv::drawContours( marker_mask, contours, -1,  
                cv::Scalar(255), CV_FILLED );  

            //cv::Mat color_tab;  
            std::cout << contours.size() << std::endl;

            cv::imshow( "image", marker_mask );  
        }
    }

    cv::waitKey(0);
    return 0;
}

得到掩码图像

将闭合环线外的部分像素值全设为0,内部全设为255.
就是在for(;;)循环里面的:

        if( (char)c == 'p' )  {
            std::cout << "processing ... " << std::endl;
            std::vector<std::vector<cv::Point> > contours;
            vector<Vec4i> hierarchy;
            cv::findContours( marker_mask, contours, 
                            CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );  

            marker_mask.setTo(cv::Scalar::all(0));  
            cv::drawContours( marker_mask, contours, -1,  
                cv::Scalar(255), CV_FILLED );  

            //cv::Mat color_tab;  
            std::cout << contours.size() << std::endl;

            cv::imshow( "image", marker_mask );  
        }

运行程序:鼠标手动绘制一个闭合环线,按P生成掩码图像
这里写图片描述

知识点

  1. 清零函数
    OpenCV1的函数

    cvZero( marker_mask );  

    等同于OpenCV2的函数:

    marker_mask.setTo(cv::Scalar::all(0));
  2. 复制函数和克隆函数
    OpenCV1的函数

    cvCopy( 原图, 副本);  

    等同于OpenCV2的函数:

    原图.copyTo(副本);

    或着

    副本 = 原图.clone();

参考网站:
http://blog.csdn.net/wangyaninglm/article/details/41864021
http://answers.opencv.org/question/26415/cvzero-fucntion-for-c-api/

推荐阅读