使用 python 和 OpenCV 对图像上的细胞进行计数
Count cells on image using python and OpenCV
我正在尝试编写一种算法来计算图像上的点(单元格)。
这是我到目前为止制作的脚本:
import numpy as np
import cv2
import os
for dirname in os.listdir("images/"):
for filename in os.listdir("images/" + dirname + "/"):
# Image read
img = cv2.imread("images/" + dirname + "/" + filename, 0)
# Denoising
denoisedImg = cv2.fastNlMeansDenoising(img);
# Threshold (binary image)
# thresh – threshold value.
# maxval – maximum value to use with the THRESH_BINARY and THRESH_BINARY_INV thresholding types.
# type – thresholding type
th, threshedImg = cv2.threshold(denoisedImg, 200, 255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU) # src, thresh, maxval, type
# Perform morphological transformations using an erosion and dilation as basic operations
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morphImg = cv2.morphologyEx(threshedImg, cv2.MORPH_OPEN, kernel)
# Find and draw contours
contours, hierarchy = cv2.findContours(morphImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contoursImg = cv2.cvtColor(morphImg, cv2.COLOR_GRAY2RGB)
cv2.drawContours(contoursImg, contours, -1, (255,100,0), 3)
cv2.imwrite("results/" + dirname + "/" + filename + "_result.tif", contoursImg)
textFile = open("results/results.txt","a")
textFile.write(filename + " Dots number: {}".format(len(contours)) + "\n")
textFile.close()
这是我的输入图像:
这是我的结果:
现在这个脚本在那个输入上工作得很好,但是当我切换到像这样的其他输入时:
我得到了一个非常模糊的结果:
我希望只保留以下点:
- 全面发展
或:
- 哪些点在亮度方面处于其他点的前 10%
- 哪些 "big" 就足够了(相对于图像,假设消除表面底部 10% 的点)。
我阅读了有关创建 "is_contour_bad" 函数的内容,我可以用它来确定轮廓是否有问题并且应该被删除。
https://www.pyimagesearch.com/2015/02/09/removing-contours-image-using-python-opencv/
我尝试实施它但没有得到任何结果。尽管如此,这个想法对我来说还是不错的。
我也考虑过根据图像调整阈值和 erosions/dilatations 但实际上最好的是能够对之前列举的每个参数采取行动。不过,如果您有想法自动查找图像的有用属性以在其上应用正确的过滤器,那可能会很有趣。
如果您有任何想法或代码,即使很小,也可以帮助我实现该目标,那就太棒了。
在此先感谢您的帮助。
删除不圆润和小的点的一种方法是使用打开操作(你已经在使用),带有你想要的最小点大小的圆形结构元素(每个小于结构元素的点都将被删除)。在下面的图片中,有一个与您的问题类似的示例,其中以这种方式删除了小点(来源:https://homepages.inf.ed.ac.uk/rbf/HIPR2/open.htm). Also, OpenCV has an implementation of this operation (https://docs.opencv.org/trunk/d9/d61/tutorial_py_morphological_ops.html)。
事实上,你已经使用了这个操作,但在我看来,下面这行定义的结构元素似乎太小了:
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
此外,由于您显然使用了不同分辨率的图像,因此您可以根据图像的分辨率调整结构元素的大小。
我正在尝试编写一种算法来计算图像上的点(单元格)。
这是我到目前为止制作的脚本:
import numpy as np
import cv2
import os
for dirname in os.listdir("images/"):
for filename in os.listdir("images/" + dirname + "/"):
# Image read
img = cv2.imread("images/" + dirname + "/" + filename, 0)
# Denoising
denoisedImg = cv2.fastNlMeansDenoising(img);
# Threshold (binary image)
# thresh – threshold value.
# maxval – maximum value to use with the THRESH_BINARY and THRESH_BINARY_INV thresholding types.
# type – thresholding type
th, threshedImg = cv2.threshold(denoisedImg, 200, 255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU) # src, thresh, maxval, type
# Perform morphological transformations using an erosion and dilation as basic operations
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
morphImg = cv2.morphologyEx(threshedImg, cv2.MORPH_OPEN, kernel)
# Find and draw contours
contours, hierarchy = cv2.findContours(morphImg, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contoursImg = cv2.cvtColor(morphImg, cv2.COLOR_GRAY2RGB)
cv2.drawContours(contoursImg, contours, -1, (255,100,0), 3)
cv2.imwrite("results/" + dirname + "/" + filename + "_result.tif", contoursImg)
textFile = open("results/results.txt","a")
textFile.write(filename + " Dots number: {}".format(len(contours)) + "\n")
textFile.close()
这是我的输入图像:
这是我的结果:
现在这个脚本在那个输入上工作得很好,但是当我切换到像这样的其他输入时:
我得到了一个非常模糊的结果:
我希望只保留以下点:
- 全面发展
或:
- 哪些点在亮度方面处于其他点的前 10%
- 哪些 "big" 就足够了(相对于图像,假设消除表面底部 10% 的点)。
我阅读了有关创建 "is_contour_bad" 函数的内容,我可以用它来确定轮廓是否有问题并且应该被删除。
https://www.pyimagesearch.com/2015/02/09/removing-contours-image-using-python-opencv/
我尝试实施它但没有得到任何结果。尽管如此,这个想法对我来说还是不错的。
我也考虑过根据图像调整阈值和 erosions/dilatations 但实际上最好的是能够对之前列举的每个参数采取行动。不过,如果您有想法自动查找图像的有用属性以在其上应用正确的过滤器,那可能会很有趣。
如果您有任何想法或代码,即使很小,也可以帮助我实现该目标,那就太棒了。
在此先感谢您的帮助。
删除不圆润和小的点的一种方法是使用打开操作(你已经在使用),带有你想要的最小点大小的圆形结构元素(每个小于结构元素的点都将被删除)。在下面的图片中,有一个与您的问题类似的示例,其中以这种方式删除了小点(来源:https://homepages.inf.ed.ac.uk/rbf/HIPR2/open.htm). Also, OpenCV has an implementation of this operation (https://docs.opencv.org/trunk/d9/d61/tutorial_py_morphological_ops.html)。
事实上,你已经使用了这个操作,但在我看来,下面这行定义的结构元素似乎太小了:
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
此外,由于您显然使用了不同分辨率的图像,因此您可以根据图像的分辨率调整结构元素的大小。