图像去水印/修复

实际应用中,我们的图像常常会被噪声腐蚀,这些噪声可能是划痕,涂鸦等。或者图像的部分本身已经损毁。这就需要对图片进行还原。

结合另一篇内容:OpenCV–0016:图像ROI与ROI操作

图像的修复原理:

利用那些已经被破坏的区域的边缘,即边缘的颜色和结构,根据这些图像留下的信息去推断被破坏的信息区域的信息内容,然后对破坏区进行填补,以达到图像修补的目的。

OpenCV中的两种修复算法

1、inpaint函数
  • 说明
    使用区域邻域恢复图像中的选定区域。

    函数实现关键是图像掩码的确定,可以通过阈值筛选或者手工选定

    该功能从区域边界附近的像素重建选定的图像区域。该功能可用于去除扫描照片上的灰尘和划痕,或去除静止图像或视频中不需要的物体。

  • 声明

    void inpaint(
       InputArray src, 
       InputArray inpaintMask,          
       OutputArray dst, 
       double inpaintRadius, 
       int flags 
    );
    
  • 参数

    src输入8位或16位无符号或32位浮点型1通道或8位3通道图像。
    inpaintMask图像的掩码,单通道图像,大小跟原图像一致,inpaintMask图像上除了需要修复的部分之外其他部分的像素值全部为0;
    dst输出的经过修复的图像;
    inpaintRadius修复算法取的邻域半径,用于计算当前像素点的差值;
    flag修复算法,有两种:INPAINT_NS 和I NPAINT_TELEA;
2、OpenCV中实现的两种图像修复算法
2.1、INPAINT_NS : 基于Navier-Stokes的修复方法

在下图中,我们的目标是填充暗区并获得一个看起来像右边的图像。
在这里插入图片描述
我们如何填充这个黑色的区域?

  • 第一个约束:边缘进入点A应该连接边缘离开点B。
  • 另一个约束:连接A和B的曲线右边的区域应该是白色,而左边的区域应该是蓝色的。

以上两个约束基本上要求:保留渐变(即边缘特征)和继续在平滑区域中传播颜色信息。

基于Bertalmio,Marcelo,Andrea L. Bertozzi和Guillermo Sapiro于2001年撰写的“Navier-Stokes,流体动力学和图像和视频修补”一文。该算法基于流体动力学并利用偏微分方程。基本原则是heurisitic。它首先沿着已知区域的边缘行进到未知区域(因为边缘是连续的)。它继续等照片(连接具有相同强度的点的线,就像轮廓连接具有相同高度的点一样),同时在修复区域的边界处匹配渐变矢量。为此,使用来自流体动力学的一些方法。获得颜色后,填充颜色以减少该区域的最小差异。使用标志cv2.INPAINT_NS启用此算法。

2. INPAINT_TELEA : 基于图像梯度的快速匹配方法(Telea法)

该方法实现使用不同的技术解决了相同的约束。作者不使用图像拉普拉斯算子作为平滑度的估计,而是使用像素的已知图像邻域上的加权平均值来补绘。已知的邻域像素和梯度用于估计要修复的像素的颜色。

基于Alexandru Telea于2004年发表的“基于快速行进方法的图像修复技术”。它基于快速行进方法。考虑图像中要修复的区域。算法从该区域的边界开始,然后进入区域内,逐渐填充边界中的所有内容。它需要在邻近的像素周围的一个小邻域进行修复。该像素由邻居中所有已知像素的归一化加权和代替。选择权重是一个重要的问题。对于靠近该点的那些像素,靠近边界的法线和位于边界轮廓上的像素,给予更多的权重。一旦像素被修复,它将使用快速行进方法移动到下一个最近的像素。 FMM确保首先修复已知像素附近的像素,这样它就像手动启发式操作一样工作。使用标志cv2.INPAINT_TELEA启用此算法。

3、应用
3.1 应用一

1.图像转化成灰度图像
2.图像通过阈值处理生成Mask
3.对Mask进行膨胀处理,增加Mask面积
4.图像修复

void inpaintTest(Mat& src) {
	//1.图像转化成灰度图像
	Mat gray;
	cvtColor(src, gray, COLOR_BGR2GRAY);
	//2.图像通过阈值处理生成Mask
	Mat maskBinary = Mat(src.size(), CV_8UC1, Scalar::all(0));
	threshold(gray, maskBinary,240,255, THRESH_BINARY);
	imshow("maskBinary", maskBinary);
	//3.对Mask进行膨胀处理,增加Mask面积
	Mat maskDilate;
	Mat kernel=getStructuringElement(MORPH_RECT, Size(3, 3));
	dilate(maskBinary, maskDilate, kernel);
	imshow("maskDilate", maskDilate);
	//4.图像修复
	Mat dst_telea = src.clone();
	Mat dst_ns = src.clone();
	inpaint(src, maskDilate, dst_ns, 1, INPAINT_NS);
	inpaint(src, maskDilate, dst_telea, 1, INPAINT_TELEA);
	imshow("INPIANT_TELEA", dst_telea);
	imshow("INPAINT_NS", dst_ns);

}
int main() {
	Mat src;
	src = imread("D:/test/girl.jpg");
	if (src.empty()) {
		cout << "读取图片出现错误···" << endl;
	}
	imshow("src", src);
	inpaintTest(src);

	waitKey(0);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
关键点:找出原图中需要去除的部分的像素范围,通过阈值的方式,将需要去除的像素范围内的部分全部提取出来,其余部分置黑色,以此形成一个模板。

缺点显而易见:在阈值范围内的所有像素点都受到影响。从而影响原本图像的完整性。消除白色像素点比较好。对于黑色像素点效果很差。

3.2 应用二

蒙版必须和原图案的大小相同。

void quShuiYinTest() {
	Mat src = imread("D:/test/src3.jpg");
	ellipse(src, Point(300, 240), Size(80, 40), 0, 0, 360, Scalar(143, 3, 223));
	putText(src, "WaitFoF", Point(240, 250), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 255, 0));
	imshow("src", src);

	//Mat mask;
	//inRange(src, Scalar(0, 0, 250), Scalar(0, 0, 255), mask);
	Mat mask = Mat(src.size(), CV_8UC1, Scalar::all(0));
	ellipse(mask, Point(300, 240), Size(80, 40), 0, 0, 360, Scalar(255, 255, 255));
	putText(mask, "WaitFoF", Point(240, 250), FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 255, 255));
	imshow("mask", mask);

	//3. 修复
	Mat dst_ns = src.clone();
	Mat dst_telea = src.clone();
	inpaint(src, mask, dst_ns, 3, INPAINT_NS);
	inpaint(src, mask, dst_telea, 3, INPAINT_TELEA);

	imshow("dst_ns", dst_ns);
	imshow("dst_talea", dst_telea);



}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

学习:
[OpenCV实战]34 使用OpenCV进行图像修复

用python+OpenCV去除图片水印

opencv 浅谈图像修复

OpenCV—python 图像修复(去除水印)

【超强干货】图像去噪、图像去水印、图像篡改、图像修复超强干货论文+源码整理

图像去水印

inpaint函数

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值