移除图像中小于n大小(噪声)的像素-打开CV python

2024-06-28 22:15:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试消除图像中的噪声,目前正在运行此代码

import numpy as np
import argparse
import cv2
from skimage import morphology

# Construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True,
    help = "Path to the image")
args = vars(ap.parse_args())

# Load the image, convert it to grayscale, and blur it slightly
image = cv2.imread(args["image"])

cv2.imshow("Image", image)
cv2.imwrite("image.jpg", image)

greenLower = np.array([50, 100, 0], dtype = "uint8")
greenUpper = np.array([120, 255, 120], dtype = "uint8")

green = cv2.inRange(image, greenLower, greenUpper)
#green = cv2.GaussianBlur(green, (3, 3), 0)

cv2.imshow("green", green)
cv2.imwrite("green.jpg", green)

cleaned = morphology.remove_small_objects(green, min_size=64, connectivity=2)

cv2.imshow("cleaned", cleaned)
cv2.imwrite("cleaned.jpg", cleaned)



cv2.waitKey(0)

但是,尽管使用了remove_small_objects功能,图像似乎并没有从“绿色”更改为“已清理”。这是为什么,我该如何清理图像?理想情况下,我只想分离白菜的图像。

我的想法是在阈值化之后去除小于100的像素,然后用模糊来平滑图像,并填充被白色包围的黑洞——这就是我在matlab中所做的。如果有人能指导我得到与我的matlab实现相同的结果,那将是非常感谢的。谢谢你的帮助。

编辑:在更改代码时犯了一些错误,更新到当前状态并显示3个图像

图片:

enter image description here

绿色:

enter image description here

干净:

enter image description here

我的目标是从matlab实现中获得如下图片:

enter image description here


Tags: the代码图像imageimportnpargsgreen
3条回答

似乎您要删除的是一组断开连接的小blob。 我认为用正确的内核删除它们会有很好的效果。

给定一个nxn内核,search将内核移动到图像中,并用内核中的最小像素替换中心像素。 然后您可以expand()生成的图像以恢复绿色部分的侵蚀边缘。

另一个选择是使用fastndenoising

#####  option 1
kernel_size = (5,5) # should roughly have the size of the elements you want to remove
kernel_el = cv2.getStructuringElement(cv2.MORPH_RECT, kernel_size)
eroded =   cv2.erode(green, kernel_el, (-1, -1))
cleaned = cv2.dilate(eroded, kernel_el, (-1, -1))

##### option 2
cleaned = cv2.fastNlMeansDenoisingColored(green, h=10)

预处理

当你过滤一个图像的时候,一个好主意是降低图像的分辨率或者使其模糊一点;这样相邻的像素在颜色上会变得更加均匀,所以它会缓和图像上的亮点和暗点,并使洞远离你的遮罩。

img = cv2.imread('image.jpg')
blur = cv2.GaussianBlur(img, (15, 15), 2)
lower_green = np.array([50, 100, 0])
upper_green = np.array([120, 255, 120])
mask = cv2.inRange(blur, lower_green, upper_green)
masked_img = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow('', masked_img)
cv2.waitKey()

Blurred filter

色彩空间

目前,你正试图通过不同亮度的颜色范围来包含一个图像——你想要绿色像素,不管它们是暗的还是亮的。这在HSV色彩空间中更容易实现。查看我的答案here深入HSV色彩空间。

img = cv2.imread('image.jpg')
blur = cv2.GaussianBlur(img, (15, 15), 2)
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)
lower_green = np.array([37, 0, 0])
upper_green = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower_green, upper_green)
masked_img = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow('', masked_img)
cv2.waitKey()

HSV filtering

二值图像/掩模中的噪声去除

ngalstyan提供的answer展示了如何用形态学很好地实现这一点。你想做的是称为打开,这是一个组合的过程,即腐蚀(或多或少只是移除某个半径内的所有东西)然后膨胀(无论移除多少都会添加回任何剩余的对象)。在OpenCV中,这是通过^{}完成的。该页上的教程显示了它的工作原理。

img = cv2.imread('image.jpg')
blur = cv2.GaussianBlur(img, (15, 15), 2)
hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV)
lower_green = np.array([37, 0, 0])
upper_green = np.array([179, 255, 255])
mask = cv2.inRange(hsv, lower_green, upper_green)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15))
opened_mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
masked_img = cv2.bitwise_and(img, img, mask=opened_mask)
cv2.imshow('', masked_img)
cv2.waitKey()

Opened mask

填补空白

在上面,opening被显示为从二进制掩码中移除小白点的方法。关闭是相反的操作——从被白色包围的图像中删除黑色块。您可以使用与上面相同的想法,但使用^{}。在你的情况下,这甚至不是必要的,因为面具没有任何洞。但如果是的话,你可以用关门来关上它们。你会注意到我的第一步实际上是去掉了底部的一小块植物。实际上,您可以先关闭,然后打开以删除其他地方的伪位来填补这些空白,但对于此图像,这可能不是必需的。

尝试阈值的新值

你可能想要更舒适地使用不同的颜色空间和阈值级别,以获得对特定图像最有效的感觉。它还没有完成,界面有点不稳定,但是我有一个工具,你可以在线使用它在不同的颜色空间中尝试不同的阈值;如果你愿意,可以查看here。这就是我如何快速找到你的形象价值。

不过,上面的问题是用cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)解决的。但是,如果有人想使用morphology.remove_small_objects来删除小于指定大小的区域,那么这个答案可能会有帮助。

我用来去除上面图像的噪声的代码是:

import numpy as np
import cv2
from skimage import morphology
# Load the image, convert it to grayscale, and blur it slightly
image = cv2.imread('im.jpg')
cv2.imshow("Image", image)
#cv2.imwrite("image.jpg", image)
greenLower = np.array([50, 100, 0], dtype = "uint8")
greenUpper = np.array([120, 255, 120], dtype = "uint8")
green = cv2.inRange(image, greenLower, greenUpper)
#green = cv2.GaussianBlur(green, (3, 3), 0)
cv2.imshow("green", green)
cv2.imwrite("green.jpg", green)
imglab = morphology.label(green) # create labels in segmented image
cleaned = morphology.remove_small_objects(imglab, min_size=64, connectivity=2)

img3 = np.zeros((cleaned.shape)) # create array of size cleaned
img3[cleaned > 0] = 255 
img3= np.uint8(img3)
cv2.imshow("cleaned", img3)
cv2.imwrite("cleaned.jpg", img3)
cv2.waitKey(0)

清理后的图像如下所示:

enter image description here

要使用morphology.remove_small_objects,必须首先标记blob。为此,我使用imglab = morphology.label(green)。标记是这样做的,第一个blob的所有像素都编号为1。类似地,第7个blob的所有像素都编号为7,依此类推。因此,在移除小区域后,剩余blob的像素值应设置为255,以便cv2.imshow()可以显示这些blob。为此,我创建了一个数组img3,其大小与已清理图像的大小相同。我使用img3[cleaned > 0] = 255行将值大于0的所有像素转换为255。

相关问题 更多 >