图像处理:基于cv2.inpaint()图像修补

  • Post author:
  • Post category:其他


前言

今天我们将学习如何通过一种“修复”的方法消除旧照片中的小噪音,笔画等。当然,经过我的测试你也可以将其用于削弱混杂了其他的颜色的图像。

实验背景

大多数人家都会有一些旧的的旧化照片,上面有黑点,一些笔触等。你是否曾经想过将其还原?我们不能简单地在绘画工具中擦除它们,因为它将简单地用白色结构代替黑色结构,这是没有用的。在这些情况下,将使用一种称为图像修复的技术。基本思想很简单:用附近的像素替换那些不良区域,使其看起来和邻近的协调。考虑下面显示的图像(摘自Wikipedia)。

同样的,今天我在这里也要进行一些拓展,采用我的方法也可以用于削弱混入了图像中的其他颜色。

获取图像的掩膜图

下面的图片是经过人脸检测后的图片,现在我并不想要它这个框。

运行下面的脚本进行颜色提取

import cv2
import numpy as np
import pyps.pyzjr.utility as zjr

def empty(a):
    pass

path = 'AI.png'
cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars",640,250)
cv2.createTrackbar("Hue Min","TrackBars",58,179,empty)
cv2.createTrackbar("Hue Max","TrackBars",60,179,empty)
cv2.createTrackbar("Sat Min","TrackBars",73,255,empty)
cv2.createTrackbar("Sat Max","TrackBars",255,255,empty)
cv2.createTrackbar("Val Min","TrackBars",36,255,empty)
cv2.createTrackbar("Val Max","TrackBars",255,255,empty)
#经过测试得到的掩码58 60 73 255 36 255
while True:
    img = cv2.imread(path)
    #图像转化为HSV格式,H:色调S:饱和度V:明度
    imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    h_min = cv2.getTrackbarPos("Hue Min","TrackBars")
    h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
    s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
    s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
    v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
    v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
    print(h_min,h_max,s_min,s_max,v_min,v_max)

    #创建一个蒙版,提取需要的颜色为白色,不需要的颜色为白色
    lower = np.array([h_min,s_min,v_min])
    upper = np.array([h_max,s_max,v_max])
    mask = cv2.inRange(imgHSV,lower,upper)
    imgResult = cv2.bitwise_and(img,img,mask=mask)

    imgStack = zjr.stackImages(0.7,([img,imgHSV],[mask,imgResult]))
    cv2.imshow("Stacked Images", imgStack)

    cv2.waitKey(1)

注:import pyps.pyzjr.utility as zjr,此为我的私库函数,大家可以使用matplotlib.pyplot as plt代替此功能。

这里有关于HSV的一些

介绍

,下面是一些常见颜色的HSV值,大家可以参考着在轨迹栏中进行调整,顺序都是从上到下,具体还是要根据实际情况进行调整。

详解cv2.inpaint()

cv2.inpaint是用于图像修复的函数。它可以自动根据给定的掩膜(mask)来修复图像,即用图像中的其他部分来填充掩膜部分的像素。函数的语法如下:

dst = cv2.inpaint(src, inpaintMask, inpaintRadius, flags)

其中的参数的含义如下:



  • src

    :

    要修复的原始图像


  • inpaintMask

    :

    修复图像的掩膜,即需要被修复的像素区域


  • inpaintRadius

    :

    修复半径,即掩膜的像素周围需要参考的区域半径


  • flags

    :

    修复算法的标志。有两个可选值:cv2.INPAINT_TELEA和cv2.INPAINT_NS。默认为cv2.INPAINT_TELEA。

其中,cv2.INPAINT_TELEA和cv2.INPAINT_NS分别代表基于快速行进算法(Fast Marching Method)和基于Navier-Stokes方程(Navier-Stokes equation)的修复算法,前者更快、后者更准确。

修补图像

接着,我们需要将上面脚本的这几行放进下面的测试代码中。

lower = np.array([h_min,s_min,v_min])
upper = np.array([h_max,s_max,v_max])
mask = cv2.inRange(imgHSV,lower,upper)
imgResult = cv2.bitwise_and(img,img,mask=mask)

将调整好的值,从控制台中copy给h_min, h_max, s_min, s_max, v_min, v_max

import cv2
import numpy as np
import pyps.pyzjr.utility as zjr

path = 'AI.png'
img = cv2.imread(path)
Grayimg = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

h_min, h_max, s_min, s_max, v_min, v_max = 58, 60, 73, 255, 36, 255
lower = np.array([h_min,s_min,v_min])
upper = np.array([h_max,s_max,v_max])
imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask_black = cv2.inRange(imgHSV, lower, upper)
imgResult = cv2.bitwise_and(img,img,mask=mask_black)
dst = cv2.inpaint(img, mask_black, 10, cv2.INPAINT_TELEA)
mask_white = cv2.bitwise_not(mask_black)

stackimg=zjr.stackImages(0.7,([img,imgResult],[mask_white,dst]))
cv2.imshow("repair_img",stackimg)
cv2.imwrite("AI2.png",dst)
cv2.waitKey(0)

运行结果如下所示, 效果比较不错,整体看来只有头发那里有些许模糊。

改进建议

如果你有现成的掩膜图,那么去除的效果会更好;如果你需要遍历文件进行修改,所获得的HSV值并不适用于每一张图,建议单独进行处理。


改进方式:

  • 修改cv2.inpaint()参数,修复半径可以在合适的范围内进行修改,修复算法的标志,有两种方式可选cv2.INPAINT_TELEA和cv2.INPAINT_NS,其特点可以看看上面给出的详解,实际应用中,需要两种都试试,并不是cv2.INPAINT_NS就对这种图更准确。
  • 使用颜色提取脚本,可以将HSV值稍微调整大一些,可能会包含了一些其他的颜色,但对于我们的目标颜色(绿色)能够提取的更加完整,尤其是面对颜色比较复杂的场景,比如热力图,这个可以后期个人去尝试。
  • 使用np切片的方法,对掩膜图特定的区域进行保护。
x_threshold = 500
mask_black[:, x_threshold:] = 0
  • 如果是用于检测,对于部分不是很理想的图像,可以使用ps细致修改,当然这是你在用来我这个方法后,作为压箱底的措施。

总结

效果是达到了我的预期,本来按照我个人的想法也是将目标颜色的附近颜色进行替换,那这不得不遍历图像得像素点,但还好有Opencv中有inpaint()函数,得以实现本次实验。在这里我们就不讨论它的实现原理了,大家在CSDN上可以搜索到很多得资料。

实验效果图


2023年5月7日修正

出现了一个bug,今天在测试时,文字为白色遮盖了我原本的图像,当我对图像进行上面的操作时,发现文字没有被消去,反而变为了黑色,如果要去消除,还需要再进行一次黑色文字的颜色提取,再用图像修补才达到我的预期。



版权声明:本文为m0_62919535原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。