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

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

问题描述

我正在使用Python 2.7,我使用以下Python和Matlab函数来消除此图像中的噪音和填充空洞





1。使用Python和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. 使用 ndimage.binary_closing 在python和scipy中使用的代码:

      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. Matlab中使用的代码:我使用了 imfill bwareaopen


我得到的结果如下所示:



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



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



我从MATLAB处理得到的第三张图片,imfill工作完美,无需将基本的白色像素转换为黑色。



所以,我的问题是,是否有任何Python 2.7的方法,我可以删除某些区域下方的噪音,并在Matlab中准确填充白色斑点?还有一件事是,我想找出最后处理的blob的质心和区域,以便进一步使用。我可以使用 cv2.connectedComponentsWithStats 找出这些,但我想在去除噪音和填充blob后找到区域和质心。



谢谢。



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

解决方案

来自



请注意,在这种情况下,我只需在处设置背景的起始像素(0,0)。然而,可能存在例如沿着中心向下的白线,其将切断该操作以停止填充(即,停止寻找背景)图像的另一半。更健壮的方法是遍历图像上的所有边缘像素,并在每次遇到黑色像素时进行泛光填充。您可以使用 cv2.floodFill()中的掩码参数更轻松地完成此操作,这样您就可以继续更新每次都有掩码。






要查找每个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天全站免登陆