如何使用python opencv识别图片中细胞内切圆的直径,四角周围不是圆形的剔除掉?

问题遇到的现象和发生背景
问题相关代码,请勿粘贴截图
运行结果及报错内容

img

我的解答思路和尝试过的方法
我想要达到的结果

这是我写的代码,但是效果不怎么样


 # 加载环境包
# -*- coding: utf-8 -*-

import cv2
import numpy as np

# 图片简单处理
img = cv2.imread('./file/test.jpg')  # 读取图片
GrayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度化

GrayImage = cv2.medianBlur(GrayImage, 5)  # 中值模糊

# 阈值处理,输入图片默认为单通道灰度图片
ret, th1 = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY)  # 固定阈值二值化
# threshold为固定阈值二值化
# 第二参数为阈值
# 第三参数为当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值(一般情况下,都是256色,所以默认最大为255)
# thresh_binary是基于直方图的二值化操作类型,配合threshold一起使用。此外还有cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
th2 = cv2.adaptiveThreshold(GrayImage, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 3, 5)
# adaptiveThreshold自适应阈值二值化,自适应阈值二值化函数根据图片一小块区域的值来计算对应区域的阈值,从而得到也许更为合适的图片。
# 第二参数为当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值(一般情况下,都是256色,所以默认最大为255)
# 第三参数为阈值计算方法,类型有cv2.ADAPTIVE_THRESH_MEAN_C,cv2.ADAPTIVE_THRESH_GAUSSIAN_C
# 第四参数是基于直方图的二值化操作类型,配合threshold一起使用。此外还有cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
# 第五参数是图片中分块的大小
# 第六参数是阈值计算方法中的常数项
th3 = cv2.adaptiveThreshold(GrayImage, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 3, 5)
# 同上
kernel = np.ones((5, 5), np.uint8)  # 创建全一矩阵,数值类型设置为uint8
erosion = cv2.erode(th2, kernel, iterations=1)  # 腐蚀处理
dilation = cv2.dilate(erosion, kernel, iterations=1)  # 膨胀处理

imgray = cv2.Canny(erosion, 40, 200)  # Canny算子边缘检测
cv2.imshow('1', imgray)
cv2.waitKey(0)  # 无穷大等待时间

circles = cv2.HoughCircles(imgray, cv2.HOUGH_GRADIENT,
                           1, #3
                           80, #4
                           param1=200, #5
                           param2=2, #6
                           minRadius=40,
                           maxRadius=45)  # 霍夫圆变换
# 第3参数默认为1
# 第4参数表示圆心与圆心之间的距离(太大的话,会很多圆被认为是一个圆)
# 第5参数默认为100
# 第6参数根据圆大小设置(圆越小设置越小,检测的圆越多,但检测大圆会有噪点)
# 第7圆最小半径
# 第8圆最大半径
circles = np.uint16(np.around(circles))
# np.uint16数组转换为16位,0-65535
# np.around返回四舍五入后的值

P = circles[0]  # 去掉circles数组一层外括号
for i in P:
    # 画出外圆
    cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2)  # 第二参数()内是圆心坐标,第三参数是半径,第四参数()内是颜色,第五参数是线条粗细
    # 画出圆心
    cv2.circle(img, (i[0], i[1]), 2, (0, 0, 255), 3)
print("圆的个数是:")
print(len(P))
for i in P:
    r = int(i[2])
    x = int(i[0])
    y = int(i[1])
    print("圆心坐标为:", (x, y))
    print("圆的半径是:", r)

cv2.imshow('detected circles', img)  # 第一参数为窗口名称

cv2.waitKey(0)  # 无穷大等待时间
cv2.destroyAllWindows()

效果:

img

用霍夫变换试试,识别出圆形,标注出来后输出标注框的长度

import cv2  
import numpy as np  
import matplotlib.pyplot as plt  
  
img = cv2.imread('C:\\Users\\tina\\Pictures\\ahh\\ball.jpg')  
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  
  
plt.subplot(121),plt.imshow(gray,'gray')  
plt.xticks([]),plt.yticks([])  
  
circles1 = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,  
600,param1=100,param2=30,minRadius=80,maxRadius=97)  
circles = circles1[0,:,:]  
circles = np.uint16(np.around(circles))  
for i in circles[:]:   
    cv2.circle(img,(i[0],i[1]),i[2],(255,0,0),5)  
    cv2.circle(img,(i[0],i[1]),2,(255,0,255),10)  
    cv2.rectangle(img,(i[0]-i[2],i[1]+i[2]),(i[0]+i[2],i[1]-i[2]),(255,255,0),5)  
      
print("圆心坐标",i[0],i[1])  
plt.subplot(122),plt.imshow(img)  
plt.xticks([]),plt.yticks([])