Python 2.7:在 Python 中打开和关闭二进制图像的区域不太准确 [英] Python 2.7: Area opening and closing binary image in Python not so accurate

查看:16
本文介绍了Python 2.7:在 Python 中打开和关闭二进制图像的区域不太准确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 Python 2.7,我使用了以下 Python 和 Matlab 函数来消除噪声并填充此图像中的孔

.

1.使用 Python 和 Opencv 去除噪声和填充孔的代码

img = cv2.imread("binar.png",0)内核 = np.ones((5,5),np.uint8)打开 = cv2.morphologyEx(img, cv2.MORPH_OPEN, 内核)关闭 = cv2.morphologyEx(打开,cv2.MORPH_CLOSE,内核)

  1. 使用 ndimage.binary_closure 在 python 和 scipy 中使用的代码:

     im = cv2.imread("binar.png", cv2.IMREAD_GRAYSCALE)open_img = ndimage.binary_opening(im)close_img = ndimage.binary_close(open_img)clg = close_img.astype(np.int)

  2. Matlab 中使用的代码:我使用了 imfillbwareaopen.

我得到的结果如下所示:

使用 nd.image.binary_closure 的第一张图片.我的问题是它没有完全填满所有的白色斑点.我们可以看到中间的黑色部分仍然存在.

使用 cv2.morphologyEx 的第二张图片.这也有同样的问题,因为它在白色斑点之间也有一些小的白色部分.在这里,我又遇到了一个问题.它将一些白色像素转换为黑色,否则不应该.我在图 2 中提到了那些带有红色的区域.红色突出显示的部分与较大的一个斑点相连,但即使如此,它们也会转换为黑色像素.

我从 MATLAB 处理中获得的第三张图像,其中 imfill 完美运行,无需将基本白色像素转换为黑色.

所以,我的问题是,是否有任何适用于 Python 2.7 的方法可以消除特定区域以下的噪声并像在 Matlab 中一样准确地填充白色斑点?还有一件事是,我想找出那些最终处理过的 blob 的质心和区域,以便进一步使用.我可以使用 cv2.connectedComponentsWithStats 找出这些,但我想在去除噪音和填充斑点后找到面积和质心.

谢谢.

(我认为这不是重复的,因为我想用 Python 而不是 Matlab.)

解决方案

来自

请注意,在这种情况下,我只是将背景的起始像素设置为 (0,0).但是,例如,可能会出现一条沿着中心向下的白线,这会切断此操作以停止填充(即停止查找背景)图像的另一半.更可靠的方法是遍历图像上的所有边缘像素,并在每次遇到黑色像素时进行填充.您可以使用 cv2.floodFill() 中的 mask 参数更轻松地完成此操作,它允许您每次继续更新掩码.

<小时>

要找到每个blob的质心,您可以使用轮廓检测​​和cv2.moments()来找到每个轮廓的质心,或者您也可以使用cv2.connectedComponentsWithStats() 就像你提到的.

I am using Python 2.7 and I used following Python and Matlab function for removing noises and fill holes in this image

.

1. Code to remove noise and fill holes using Python and Opencv

img = cv2.imread("binar.png",0)
kernel = np.ones((5,5),np.uint8)
open = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
close = cv2.morphologyEx(open, cv2.MORPH_CLOSE, kernel)

  1. Code used in python and scipy using ndimage.binary_closing:

      im = cv2.imread("binar.png", cv2.IMREAD_GRAYSCALE)
     open_img = ndimage.binary_opening(im)
     close_img = ndimage.binary_closing(open_img)
     clg = close_img.astype(np.int)
    

  2. Code used in Matlab: I used imfill and bwareaopen.

The results I got is shown below:

First image from using nd.image.binary_closing. My problem is it doesn't fill all white blobs fully. We can see inbetween minor black portion are still present.

Second image from using cv2.morphologyEx. Same problem in this also, as it also has some minor white portion in between white blobs. Here I faced one more problem. It converts some white pixels into black which should not be otherwise. I mentioned those areas with red color in image 2. Red highlighted portions is connected with larger one blobs but even then they get converted into black pixels.

Third image I got from MATLAB processing in which imfill work perfectly without converting essential white pixels into black.

So, my question is, Is there any method for Python 2.7 with which I can remove noises below certain area and fill the white blobs accurately as in Matlab? One more thing is, I want to find out the centroids and areas of those final processed blobs in last for further used. I can find out these using cv2.connectedComponentsWithStats but I want to find area and centroids after removing noises and filling blobs.

Thanks.

(I think this is not duplicate because I want to do it in Python not in Matlab. )

解决方案

From Matlab's imfill() documentation:

BW2= imfill(BW,locations) performs a flood-fill operation on background pixels of the input binary image BW, starting from the points specified in locations. (...)

BW2= imfill(BW,'holes') fills holes in the input binary image BW. In this syntax, a hole is a set of background pixels that cannot be reached by filling in the background from the edge of the image.

I2= imfill(I) fills holes in the grayscale image I. In this syntax, a hole is defined as an area of dark pixels surrounded by lighter pixels.

The duplicate that I flagged shows ways to accomplish the third variant usually. However for many images, the second variant will still work fine and is extremely easy to accomplish. From the first variant you see that it mentions a flood-fill operation, which can be implemented in OpenCV with cv2.floodFill(). The second variant gives a really easy method---just flood fill from the edges, and the pixels left over are the black holes which can't be reached from outside. Then if you invert this image, you'll get white pixels for the holes, which you can add to your mask to fill in the holes.

import cv2
import numpy as np

# read image, ensure binary
img = cv2.imread('image.png', 0)
img[img!=0] = 255

# flood fill background to find inner holes
holes = img.copy()
cv2.floodFill(holes, None, (0, 0), 255)

# invert holes mask, bitwise or with img fill in holes
holes = cv2.bitwise_not(holes)
filled_holes = cv2.bitwise_or(img, holes)
cv2.imshow('', filled_holes)
cv2.waitKey()

Note that in this case, I just set the starting pixel for the background at (0,0). However it's possible that there could be, e.g., a white line going down the center which would cut off this operation to stop filling (i.e. stop finding the background) for the other half of the image. The more robust method would be to go through all of the edge pixels on the image, and flood fill every time you come across a black pixel. You can accomplish this more easily with the mask parameter in cv2.floodFill(), which allows you to continue to update the mask each time.


To find the centroids of each blob, you could use contour detection and cv2.moments() to find the centroids of each contour, or you could also do cv2.connectedComponentsWithStats() like you mentioned.

这篇关于Python 2.7:在 Python 中打开和关闭二进制图像的区域不太准确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆