一种新的图像去噪方式:图像修补+斑点检测的预处理

灵感来源于我之前写的一篇博客:图像处理:基于cv2.inpaint()图像修补

这种方式可以有效的去除白色的噪点,这里我们需要一张噪点的图像,你可以用下面的代码随机生成一张噪点图片:

import cv2
import numpy as np
# import pyzjr

def addnoisy(image, n=2000):
    """
    :param image: 原始图像
    :param n: 添加椒盐的次数,默认为10000
    :return: 返回被椒盐处理后的图像
    """
    result = image.copy()
    w, h = image.shape[:2]
    for i in range(n):
        x = np.random.randint(0, w)
        y = np.random.randint(0, h)
        if np.random.randint(0, 1) == 0:
            result[x, y] = 255
    return result

img = cv2.imread("crack.jpg")
result = addnoisy(img)
cv2.imwrite("crack.png",result)

原图crack.jpg:

噪点图crack.png:

然后我们就可以用下面的代码进行处理了。 

import cv2
import numpy as np
from skimage.feature import blob_log
import matplotlib.pyplot as plt

image = cv2.imread(r"D:\PythonProject\net\High_tower\crack.png")
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

min_sigma = 1  # 斑点最小尺寸
max_sigma = 50  # 斑点最大尺寸
threshold = 0.1  # 斑点阈值,用于控制检测的灵敏度


blobs = blob_log(gray_image, min_sigma=min_sigma, max_sigma=max_sigma, threshold=threshold)

height, width = image.shape[:2]

black_image = np.zeros((height, width), dtype=np.uint8)

for blob in blobs:
    y, x, sigma = blob
    radius = int(sigma * np.sqrt(2))  # 半径是标准差乘以sqrt(2)

    cv2.circle(black_image, (int(x), int(y)), radius, (255,255,255), -1)

dst = cv2.inpaint(image, black_image, 10, cv2.INPAINT_TELEA)
cv2.imwrite("filled_blobs.png", black_image)
cv2.imwrite("dst.png", dst)

这里先是使用blob_log函数从灰度图像中检测斑点,并将检测到的斑点存储在blobs中。根据图像的高度和宽度,创建一个与输入图像相同尺寸的全黑图像,用于标记检测到的斑点。

使用for循环遍历检测到的每个斑点,然后在全黑图像上绘制一个白色的圆圈来标记斑点的位置和大小。

使用图像修复技术,将标记了斑点的全黑图像balck_image与原始图像image相结合,生成修复后的图像dst。

这里保存了两张图,一张是mask,一张是处理后的图片。

检测到的mask:

处理后的图片:

原先的图片受到了噪点的污染,在处理后的效果很不错了,这里你可以选择调参优化,或者再加一个参数小的滤波处理。

这种方法的原理是检测白色噪点位置,生成对应的掩模图,然后使用修补函数,用附近的像素点替代掉噪点,比起滤波处理会让图像变得模糊,使用这种方式让图像更加的平滑。

如果是其他颜色的污染,你可以参照本文开头给的那篇博客,里面有详细的介绍。

当然,这种方法有些缺陷,它在某些特定的场景下,表现效果很好。

猜你喜欢

转载自blog.csdn.net/m0_62919535/article/details/132899645
今日推荐