您的位置:首页 > 运维架构

【OpenCV学习笔记】三十二、分水岭算法及图像修补

2017-04-08 14:49 246 查看
分水岭算法及图像修补

1.分水岭算法——watershed()

2.图像修补——inpaint()

先上ppt:











代码:1.分水岭算法

///分水岭算法
#include "opencv2/opencv.hpp"
using namespace cv;
int main()
{
Mat srcImg = imread("bird.jpg",CV_LOAD_IMAGE_COLOR);
imshow("srcImg", srcImg);
Mat copyImg = srcImg.clone();
//1.定义标记图像markers
Mat markers(srcImg.size(),CV_8UC1,Scalar(0));
//标记背景
rectangle(markers,Point(1,1),Point(srcImg.cols-2,srcImg.rows-2),Scalar(255),1,8);
//标记鸟
rectangle(markers, Point(srcImg.cols / 2 - 20, srcImg.rows / 2 - 20), Point(srcImg.cols / 2 +20, srcImg.rows / 2 + 20), Scalar(128), -1, 8);
//标记石头
rectangle(markers, Point(srcImg.cols / 2 - 30, srcImg.rows - 50), Point(srcImg.cols / 2 + 60, srcImg.rows - 10), Scalar(64), -1, 8);
imshow("markers-input",markers);
//2.基于标记图像的分水岭算法
//将markers转换成32位单通道图像(分水岭函数要求)
markers.convertTo(markers,CV_32S);
//分水岭算法
watershed(srcImg,markers);
//将markers转换成8位单通道
markers.convertTo(markers, CV_8UC1);
imshow("markers-output", markers);
//3.提取轮廓并绘制轮廓
Mat mark1, mark2,mark3;
mark1 = markers.clone();//提取鸟的轮廓
mark2 = markers.clone();//提取石头轮廓
mark3 = markers.clone();//提取背景轮廓
//阈值化,黑中找白,找鸟
threshold(mark1,mark1,129,255,CV_THRESH_TOZERO_INV);
threshold(mark1,mark1,120,255,CV_THRESH_TOZERO);
//阈值化,黑中找白,找石头
threshold(mark2, mark2, 65, 255, CV_THRESH_TOZERO_INV);
//阈值化,黑中找白,找背景
threshold(mark3, mark3, 129, 255, CV_THRESH_BINARY);
imshow("mark1", mark1);
imshow("mark2", mark2);
imshow("mark3", mark3);
//寻找背景轮廓并绘制
vector<vector<Point>> contours3;
findContours(mark3, contours3, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
drawContours(copyImg, contours3, -1, Scalar(0, 0, 255), -1, 8);
//寻找鸟轮廓并绘制
vector<vector<Point>> contours1;
findContours(mark1,contours1,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);
drawContours(copyImg,contours1,-1,Scalar(255,0,0),-1,8);
//寻找石头轮廓并绘制
vector<vector<Point>> contours2;
findContours(mark2, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
drawContours(copyImg, contours2, -1, Scalar(0, 255, 0), -1, 8);
imshow("copyImg",copyImg);
//4.与原图像叠加
Mat result = srcImg*0.5 + copyImg*0.5;
imshow("result", result);
waitKey(0);
return 0;
}
运行结果:









代码:2.图像修补

///图像修补
#include "opencv2/opencv.hpp"
using namespace cv;
//定义原图像srcImg和目标图像dstImg
Mat srcImg = imread("face.JPG", CV_LOAD_IMAGE_COLOR);
Mat dstImg = srcImg.clone();
//定义掩码inpaintMask,同srcImg一样大小,类型为8位单通道,初始化为纯黑(掩码非0部分起作用)
Mat inpaintMask(srcImg.size(), CV_8UC1, Scalar(0));
//定义鼠标左键是否按下的标志flag
bool flag=false;
//记录鼠标左键按下时的初始坐标
int xStart, yStart;
void onMouse(int event,int x,int y,int flags,void* param)
{
switch (event)
{
case CV_EVENT_LBUTTONDOWN:
flag = true;//鼠标左键按下,flag置为true
xStart = x;//记录鼠标左键按下时的坐标
yStart = y;
break;
case CV_EVENT_MOUSEMOVE:
if (flag)
{
//在srcImg中画矩形,白色,向内填充

ae2b
rectangle(srcImg, Point(xStart, yStart), Point(x, y), Scalar(255, 255, 255), -1, 8);
//在inpaintMask中画矩形,白色,向内填充
rectangle(inpaintMask, Point(xStart, yStart), Point(x, y), Scalar(255, 255, 255), -1, 8);
}
break;
case CV_EVENT_LBUTTONUP:
flag = false;//鼠标左键抬起,flag置为false
break;
default:
break;
}
//重新显示原图srcImg
imshow("inpaint", srcImg);
//重新显示掩码图像inpaintMask
imshow("inpaintMask", inpaintMask);
}

int main()
{
imshow("srcImg", srcImg);
//定义窗口"inpaint"
namedWindow("inpaint",CV_WINDOW_AUTOSIZE);
//设置鼠标回调函数
setMouseCallback("inpaint",onMouse);
//使得一开始就显示窗口"inpaint",显示原图srcImg
imshow("inpaint", srcImg);
//使得一开始就显示窗口"inpaintMask",显示掩码图像inpaintMask
imshow("inpaintMask", inpaintMask);
//使得一开始就显示窗口"dstImg",显示目标图像dstImg
imshow("dstImg", dstImg);
//无限循环,若按下空格键(ASCII码为32),则调用inpait()函数,重新显示目标图像dstImg
while (1)
{
if (waitKey(0) == 32)//若按下空格键
{
//调用inpait()函数, 重新显示目标图像dstImg
inpaint(srcImg, inpaintMask, dstImg, 4, CV_INPAINT_NS);
imshow("dstImg", dstImg);
}
}
waitKey(0);
return 0;
}
运行结果:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: