opencv学习之路(30)、分水岭算法及图像修补

 一、简介

二、分水岭算法

 1 #include "opencv2/opencv.hpp"
 2 using namespace cv;
 3 
 4 void main()
 5 {
 6     Mat srcImg = imread("E://bird.jpg");
 7     imshow("src", srcImg);
 8     Mat dstImg = srcImg.clone();
 9     //medianBlur(srcImg, srcImg, 5);
10     //GaussianBlur(srcImg, srcImg, Size(5, 5), 0, 0);
11     Mat imgMask(srcImg.size(), CV_8U, Scalar(0));//标记图像
12     //标示背景图像
13     rectangle(imgMask, Point(1, 1), Point(srcImg.cols - 2, srcImg.rows - 2), Scalar(255), 4);
14     //标示鸟
15     rectangle(imgMask, Point(srcImg.cols / 2 - 10, srcImg.rows / 2 - 10), Point(srcImg.cols / 2 + 10, srcImg.rows / 2 + 10), Scalar(128), 10);
16     //标示岩石
17     rectangle(imgMask, Point(264, 353), Point(314, 395), Scalar(64), 10);
18     imshow("mask", imgMask);
19 
20     imgMask.convertTo(imgMask, CV_32S);
21     watershed(srcImg, imgMask);  //调用分水岭算法
22     Mat mark1, mark2;
23     imgMask.convertTo(mark1, CV_8U);
24     imshow("mark1", mark1);
25 
26     Mat mark3 = mark1.clone();
27     bitwise_not(mark1, mark2);//图像取反
28     imshow("mark2", mark2);
29     threshold(mark1, mark1, 64, 255, CV_THRESH_TOZERO_INV);//CV_THRESH_TOZERO_INV:大于阈值都为0,其余正常        找出岩石
30     threshold(mark2, mark2, 127, 255, CV_THRESH_TOZERO_INV);//因为取反后背景为0,所以筛选掉岩石后剩下的即为鸟
31     threshold(mark3, mark3, 128, 255, CV_THRESH_BINARY);//鸟为128,大于128才能为255,所以找出了背景
32 
33     vector<vector<Point>> contours;
34     vector<Vec4i> hierarcy;
35     findContours(mark1, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
36     drawContours(dstImg, contours, -1, Scalar(0, 255, 0), -1, 8);
37 
38     vector<vector<Point>> contours2;
39     vector<Vec4i> hierarcy2;
40     findContours(mark2, contours2, hierarcy2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
41     drawContours(dstImg, contours2, -1, Scalar(0, 0, 255), -1, 8);
42 
43     vector<vector<Point>> contours3;
44     vector<Vec4i> hierarcy3;
45     findContours(mark3, contours3, hierarcy3, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
46     drawContours(dstImg, contours3, -1, Scalar(255, 0, 0), -1, 8);
47 
48     Mat result = srcImg*0.5 + dstImg*0.5;
49     imshow("result", result);
50     waitKey(0);
51 }

三、图像修补

#include "opencv2/opencv.hpp"
using namespace cv;

void main()
{
    Mat srcImg = imread("E://snow.jpg");

    Mat mask(srcImg.size(), CV_8U, Scalar(0));
    rectangle(mask, Point(45, 270), Point(180, srcImg.rows), Scalar(255), -1, 8);

    Point org = Point(185, 335);
    putText(srcImg, "OpenCV", org, CV_FONT_HERSHEY_SIMPLEX, 2.2f, CV_RGB(255, 0, 0), 2);
    imshow("src", srcImg);

    //putText( mask, "OpenCV", org, CV_FONT_HERSHEY_SIMPLEX, 2.2f, CV_RGB(255,255,255),2);    
    rectangle(mask, Point(185, 270), Point(srcImg.cols, srcImg.rows), Scalar(255), -1, 8);
    imshow("mask", mask);

    Mat result;
    inpaint(srcImg, mask, result, 3, CV_INPAINT_NS); //图像修复

    imshow("result", result);
    waitKey(0);
}

四、祛痘

 1 #include "opencv2/opencv.hpp"
 2 using namespace cv;
 3 
 4 #define WINDOW_NAME0 "【原始图参考】"
 5 #define WINDOW_NAME1 "【原始图】" 
 6 #define WINDOW_NAME2 "【修补后的效果图】"
 7 
 8 Mat srcImage0, srcImage1, inpaintMask;
 9 Point previousPoint(-1, -1);//原来的点坐标
10 
11 static void ShowHelpText()
12 {
13     printf("

			   当前使用的OpenCV版本为:" CV_VERSION);
14     printf("

  ----------------------------------------------------------------------------
");
15 
16     printf("
	请在进行图像修复操作之前,在【原始图】窗口中进行适量的绘制"
17         "

	按键操作说明: 

"
18         "		【鼠标左键】-在图像上绘制白色线条

"
19         "		键盘按键【ESC】- 退出程序

"
20         "		键盘按键【2】- 恢复原始图像

"
21         "		键盘按键【1】或【SPACE】-进行图像修复操作 

");
22 }
23 
24 //-----------------------------------【On_Mouse( )函数】--------------------------------
25 //          描述:响应鼠标消息的回调函数
26 //----------------------------------------------------------------------------------------------
27 static void On_Mouse(int event, int x, int y, int flags, void*)
28 {
29     //鼠标左键弹起消息
30     if (event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))//提取flags的CV_EVENT_FLAG_LBUTTON的标志位,!()的意思是标志位无效,即鼠标左键不是拖拽动作
31         previousPoint = Point(-1, -1);
32     //鼠标左键按下消息
33     else if (event == CV_EVENT_LBUTTONDOWN)
34         previousPoint = Point(x, y);
35     //鼠标按下并移动,进行绘制
36     else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))
37     {
38         Point pt(x, y);
39         if (previousPoint.x < 0)
40             previousPoint = pt;
41         //绘制白色线条
42         line(inpaintMask, previousPoint, pt, Scalar::all(255), 5, 8, 0);
43         line(srcImage1, previousPoint, pt, Scalar::all(255), 5, 8, 0);
44         previousPoint = pt;
45         imshow(WINDOW_NAME1, srcImage1);
46     }
47 }
48 
49 void main()
50 {
51     system("color 2F");
52     ShowHelpText();
53 
54     //载入原始图并进行掩膜的初始化
55     Mat srcImage = imread("face.jpg", -1);
56     if (!srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! 
"); return; }
57     srcImage0 = srcImage.clone();
58     srcImage1 = srcImage.clone();
59     inpaintMask = Mat::zeros(srcImage1.size(), CV_8U);
60 
61     imshow(WINDOW_NAME0, srcImage0);
62     imshow(WINDOW_NAME1, srcImage1);
63     //设置鼠标回调消息
64     setMouseCallback(WINDOW_NAME1, On_Mouse, 0);
65 
66     //轮询按键,根据不同的按键进行处理
67     while (1)
68     {
69         //获取按键键值
70         char c = (char)waitKey();
71         //键值为ESC,程序退出
72         if (c == 27)
73             break;
74         //键值为2,恢复成原始图像
75         if (c == '2')
76         {
77             inpaintMask = Scalar::all(0);
78             srcImage.copyTo(srcImage1);
79             imshow(WINDOW_NAME1, srcImage1);
80         }
81         //键值为1或者空格,进行图像修补操作
82         if (c == '1' || c == ' ')
83         {
84             Mat inpaintedImage;
85             inpaint(srcImage1, inpaintMask, inpaintedImage, 3, CV_INPAINT_TELEA);
86             imshow(WINDOW_NAME2, inpaintedImage);
87         }
88     }
89 }

原文地址:https://www.cnblogs.com/little-monkey/p/7503309.html