29-分水岭算法与图像修补(EmguCV学习)
OpenCV3编程入门提炼
1、在许多实际应用中,我们需要分割图像,但无法从背景图像中获得有用信息,分水岭算法(watershed)可以将图像中的边缘转换成山脉,将均匀区域转换为山谷,这样有助于分割目标;分水岭算法是基于拓扑理论的数学形态学的分割方法:图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,集水盆的边界形成分水岭;
2、分水岭的计算过程是一个迭代标注过程,L.Vincent提出的算法中:分水岭算法分为2个步骤:①排序过程;②淹没过程;分水岭表示的是输入图像的极大值点;
3、分水岭算法API : watershed()
: 参数image:输入的图像(必须是彩色3通道图像);参数markers : 既是输入参数,也是输出参数,必须先定义一个大概的范围掩膜作为输入,类型为CV32S;
Google Translator:
4、图像修补:利用已经被破坏区域的边缘,即边缘的颜色与结构,繁殖和混合到图像中,以达到图像修补的目的;如果被破坏区域不是太大,并且在被破坏的区域边缘包含足够多的纹理和颜色,则图像修补可以较好的恢复图像,图像损坏区域过大,则无法修补; API : Inpaint()
;
LearningOpenCV3 提炼
1、分水岭算法将一幅图像中的线转换为“山”,平坦区域转换成“谷”,以有助于辅助物体分割;分水岭算法首先计算图像的梯度,这有助于在原图中形成没有纹理的谷或盆地(较低点),同时形成线条丰富的山脉或ranges(边缘高脊),然后从指定的点向盆地灌水,当图像被填满时,所有标记区域被分割开;
2、分水岭算法允许使用者标记已知是对象或背景一部分的对象或背景部分:
3、watershed()函数在使用前应该给marker寻找一些已知的标记值;参考:https://blog.csdn.net/jumencibaliang92/article/details/81514766
Code
convertTo():
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
using System.Drawing;
namespace lesson29
{
class Program
{
static void Main(string[] args)
{
//Mat src = CvInvoke.Imread("bird.jpg");
//CvInvoke.Imshow("input", src);
//Mat dst = src.Clone();
//Mat mask = new Mat(src.Size, DepthType.Cv8U, 1);
//mask.SetTo(new MCvScalar(0));
标记背景图像 (颜色填充255)
//CvInvoke.Rectangle(mask, new Rectangle(0, 0, src.Width - 2, src.Cols - 2), new MCvScalar(255), 0);
标记鸟(颜色填充128)
//CvInvoke.Rectangle(mask, new Rectangle(253, 149, 80, 69), new MCvScalar(128), 1);
标记岩石(颜色填充64)
//CvInvoke.Rectangle(mask, new Rectangle(276, 360, 37, 27), new MCvScalar(64), 1);
//CvInvoke.Imshow("mask", mask);
//mask.ConvertTo(mask, DepthType.Cv32S); //CV8U --> CV32S
//CvInvoke.Watershed(src, mask); //分水岭算法计算
//mask.ConvertTo(mask, DepthType.Cv8U);
//CvInvoke.Imshow("marker", mask);
//Mat mask_inv = new Mat();
//CvInvoke.BitwiseNot(mask, mask_inv);
//Mat marker1 = new Mat();
//Mat marker2 = new Mat();
//Mat marker3 = new Mat();
提取出掩膜中对应分量
//CvInvoke.Threshold(mask, marker1, 64, 255, ThresholdType.ToZeroInv);
//CvInvoke.Threshold(mask_inv, marker2, 127, 255, ThresholdType.ToZeroInv);
//CvInvoke.Threshold(mask, marker3, 128, 255, ThresholdType.Binary);
//CvInvoke.Imshow("marker1", marker1);
//CvInvoke.Imshow("marker2", marker2);
//CvInvoke.Imshow("marker3", marker3);
//VectorOfVectorOfPoint contours1 = new VectorOfVectorOfPoint();
//CvInvoke.FindContours(marker1, contours1, null, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
//CvInvoke.DrawContours(dst, contours1, -1, new MCvScalar(0, 0, 255), -1);
//VectorOfVectorOfPoint contours2 = new VectorOfVectorOfPoint();
//CvInvoke.FindContours(marker2, contours2, null, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
//CvInvoke.DrawContours(dst, contours2, -1, new MCvScalar(0, 255, 0), -1);
//VectorOfVectorOfPoint contours3 = new VectorOfVectorOfPoint();
//CvInvoke.FindContours(marker3, contours3, null, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
//CvInvoke.DrawContours(dst, contours3, -1, new MCvScalar(255, 0, 255), -1);
//CvInvoke.AddWeighted(src, 0.5, dst, 0.5, 0, dst);
//CvInvoke.Imshow("result", dst);
//CvInvoke.WaitKey(0);
//分水岭算法实例2
//Mat srcImg = CvInvoke.Imread("cow.jpg");
//CvInvoke.Imshow("input", srcImg);
//Mat dst = srcImg.Clone();
//Mat grayImg = new Mat();
//CvInvoke.CvtColor(srcImg, grayImg, ColorConversion.Bgr2Gray);
图片是彩色图片,阈值不好直接确定,使用OTSU算法直接计算
//CvInvoke.Threshold(grayImg, grayImg, 0, 255, ThresholdType.Otsu | ThresholdType.BinaryInv);
//CvInvoke.Imshow("threshold", grayImg);
//CvInvoke.MedianBlur(grayImg, grayImg, 5);
前景色与背景色填充不同的灰度值
//Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(7, 7), new Point(-1, -1));
//Mat fgImg = new Mat();
//CvInvoke.Erode(grayImg, fgImg, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
//CvInvoke.Imshow("foreground", fgImg);
//Mat bgImg = new Mat();
//CvInvoke.Dilate(grayImg, bgImg, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
//CvInvoke.Imshow("background", bgImg);
//CvInvoke.Threshold(bgImg, bgImg, 1, 128, ThresholdType.BinaryInv);
//CvInvoke.Imshow("background1", bgImg);
创建mark标记
//Mat mask = new Mat();
//CvInvoke.Add(fgImg, bgImg, mask);
//mask.ConvertTo(mask, DepthType.Cv32S);
//CvInvoke.Watershed(srcImg, mask);
//mask.ConvertTo(mask, DepthType.Cv8U);
//CvInvoke.Imshow("masker", mask);
//Mat marker1 = new Mat();
//Mat marker2 = new Mat();
//Mat marker3 = new Mat();
分离各背景
//CvInvoke.Threshold(mask, marker1, 128, 255, ThresholdType.ToZeroInv);
//CvInvoke.Threshold(mask, marker2, 129, 255, ThresholdType.Binary);
//CvInvoke.Imshow("marker1", marker1);
//CvInvoke.Imshow("marker2", marker2);
//VectorOfVectorOfPoint contours1 = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy1 = new VectorOfRect();
//CvInvoke.FindContours(marker1, contours1, hierarchy1, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
//CvInvoke.DrawContours(dst, contours1, -1, new MCvScalar(0, 255, 0), -1);
//VectorOfVectorOfPoint contours2 = new VectorOfVectorOfPoint();
//VectorOfRect hierarchy2 = new VectorOfRect();
//CvInvoke.FindContours(marker2, contours2, hierarchy2, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
//CvInvoke.DrawContours(dst, contours2, -1, new MCvScalar(0, 0, 255), -1);
//CvInvoke.AddWeighted(srcImg, 0.7, dst, 0.3, 0, dst);
//CvInvoke.Imshow("result", dst);
//CvInvoke.WaitKey(0);
//图像修补实例1
//Mat src = CvInvoke.Imread("snow.jpg");
//Mat dst = new Mat();
//Mat mask = new Mat(src.Size, DepthType.Cv8U, 1); //存储修补掩膜
//mask.SetTo(new MCvScalar(0));
//CvInvoke.Imshow("input", src);
//CvInvoke.Rectangle(mask, new Rectangle(46, 274, 97, 109), new MCvScalar(255), -1);//脚印修补区域
//CvInvoke.Rectangle(mask, new Rectangle(188, 322, 476, 383), new MCvScalar(255), -1);//文字修补区域
//CvInvoke.Inpaint(src, mask, dst, 3, InpaintType.NS);
//CvInvoke.Imshow("result", dst);
//CvInvoke.WaitKey(0);
//图像修补实例2 人脸祛痘
Mat src = CvInvoke.Imread("face2.jpg");
Mat dst = new Mat();
CvInvoke.Imshow("input", src);
Mat mask = CvInvoke.Imread("mark2.jpg", ImreadModes.Grayscale);
CvInvoke.Inpaint(src, mask, dst, 1, InpaintType.NS);
CvInvoke.Imshow("result", dst);
CvInvoke.WaitKey(0);
}
}
}
效果
1、图像分割成不同区域:
2、提取图像中的目标物体:
3、图像修补:
4、人脸祛痘: