删除图像中小于n尺寸(噪声)的像素 - 打开CV python

时间:2017-08-29 16:00:02

标签: python image opencv

我正在尝试删除图像中的噪点,并且目前正在运行此代码

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

3 个答案:

答案 0 :(得分:7)

预处理

当您对图像进行过滤时,一个好主意是低位图像或模糊一点;这样,相邻像素的颜色变得更加均匀,因此它可以减轻图像上更亮更暗的斑点,并防止面具上的孔洞。

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

去除二进制图像/掩码中的噪声

answer提供的ngalstyan显示了如何很好地完成形态学。您想要做的是被称为开放,这是侵蚀的组合过程(或多或少只是删除某个半径内的所有内容)然后扩张(这会增加回任何剩余的对象,但是去除)。在OpenCV中,这是通过cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)完成的。该页面上的教程展示了它如何很好地工作。

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

填补空缺

在上面,开场显示为从二进制掩码中删除少量白色的方法。 关闭是相反的操作---从图像中移除被白色包围的黑色块。您可以使用与上面相同的想法执行此操作,但使用cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)。在您的情况下,在上述情况之后甚至不需要这样做,因为面具没有任何孔。但如果确实如此,你可以关闭它们。您会注意到我的开启步骤实际上移除了底部的一小部分植物。您可以通过关闭第一个填充这些空白,然后打开以删除其他地方的虚假位,但这可能不是此图像所必需的。

尝试使用阈值处理的新值

您可能希望更灵活地使用不同的色彩空间和阈值级别,以了解哪种方法最适合特定图像。它还没有完成,界面有点不稳定,但我有一个工具可以在线使用,在不同的颜色空间中尝试不同的阈值;如果您愿意,请查看here。这就是我如何快速找到您的图像的价值。

答案 1 :(得分:1)

虽然使用 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)

清理后的图片如下所示:

Defining Stored Programs

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

答案 2 :(得分:0)

你想要删除的是一组断开的小blob。 我认为 erode()会很好地用正确的内核删除它们。

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

另一种选择是使用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)