python - Python/OpenCV —在两个图像中匹配细菌的质心点

标签 python python-3.x opencv image-processing computer-vision

我正在研究一种使用计算机视觉匹配细菌质心的算法。
因为我是计算机视觉的本科生和初学者,所以我没有专门针对此问题的代码。为了提供一些背景知识,我在GUI中使用以下功能。
'bact'变量是指细菌对象,该对象存储每种细菌的ID,位置等。

 def identify_fluor(img, frame: int):

    darkBlue = (139, 0, 0)

    for bact in fluor_at_frame(frame):
    
        pos = tuple([int(coord) for coord in bact.position[frame]])
        img = cv2.circle(img, pos, 5, darkBlue, -1)

    return img
 def identify_bright(img, frame: int):

    darkRed = (0, 0, 139)

    for bact in bright_at_frame(frame):

        pos = tuple([int(coord) for coord in bact.position[frame]])
        img = cv2.circle(img, pos, 5, darkRed, -1)

    return img
这些质心是使用当前图像处理文献中提供的最佳软件找到的。如您所见,右侧(明场)的处理图像显着欠发达,对于细菌学研究人员来说是一大障碍和烦扰。
我们需要在右边处理这些图像,因为它们的图像采样率要高得多(1秒[右]对11秒[左])。太频繁采样时,荧光图像(左)会累积化学损伤,从而失去荧光。
这些是图像完美对齐的一些实例:
Sample 1 of Bacteria Match:

Sample 2 of Bacteria Match:

Sample 3 of Bacteria Match:

在这些情况下,右侧的图像在到达下一个对齐图像之前处于中间阶段。
Sample 4 of Bacteria Match

Sample 5 of Bacteria Match

Sample 6 of Bacteria Match

明场图像
Sample 1 of Bright-Field
Sample 1 of Bright-Field
Sample 2 of Bright-Field
Sample 2 of Bright-Field
Sample 3 of Bright-Field
Sample 3 of Bright-Field
附加链接
Sample 4 of Bright-Field
Sample 5 of Bright-Field
Sample 6 of Bright-Field
Sample 7 of Bright-Field
Sample 8 of Bright-Field
Sample 9 of Bright-Field
注意:这不是作业。我正在做一个研究项目,试图获得有关细菌时间动态的信息。我试图在图像样本之一上找到可行的解决方案。
编辑#1:为澄清起见,我正在尝试使用左侧的细菌查找右侧细菌的质心。
编辑2:我不希望通过应用线性变换来匹配图像。寻找一种计算机视觉算法。
编辑#3:为了测试目的,单独添加了其他明场图像。

最佳答案

我的方法直接适用于正确的图像。
该代码在下面共享,并带有注释:
我在开始时创建了一个函数,该函数使用指定次数的圆形内核腐 eclipse 和扩大图像。

kernel = np.array([[0, 0, 1, 0, 0], 
                   [0, 1, 1, 1, 0], 
                   [1, 1, 1, 1, 1], 
                   [0, 1, 1, 1, 0], 
                   [0, 0, 1, 0, 0]], dtype=np.uint8)
def e_d(image, it):
    image = cv2.erode(image, kernel, iterations=it)
    image = cv2.dilate(image, kernel, iterations=it)
    return image
注意:右侧的图像以灰度格式在变量“img”中读取。
# Applying adaptive mean thresholding
th = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV,11,2)
# Removing small noise
th = e_d(th.copy(), 1)

# Finding contours with RETR_EXTERNAL flag and removing undesired contours and 
# drawing them on a new image.
cnt, hie = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cntImg = th.copy()
for contour in cnt:
    x,y,w,h = cv2.boundingRect(contour)
    # Elliminating the contour if its width is more than half of image width
    # (bacteria will not be that big).
    if w > img.shape[1]/2:      
        continue
    cntImg = cv2.drawContours(cntImg, [cv2.convexHull(contour)], -1, 255, -1)

# Removing almost all the remaining noise. 
# (Some big circular noise will remain along with bacteria contours)
cntImg = e_d(cntImg, 5)


# Finding new filtered contours again
cnt2, hie2 = cv2.findContours(cntImg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# Now eliminating circular type noise contours by comparing each contour's 
# extent of overlap with its enclosing circle.
finalContours = []      # This will contain the final bacteria contours
for contour in cnt2:
    # Finding minimum enclosing circle
    (x,y),radius = cv2.minEnclosingCircle(contour)
    center = (int(x),int(y))
    radius = int(radius)

    # creating a image with only this circle drawn on it(filled with white colour)
    circleImg = np.zeros(img.shape, dtype=np.uint8)
    circleImg = cv2.circle(circleImg, center, radius, 255, -1)

    # creating a image with only the contour drawn on it(filled with white colour)    
    contourImg = np.zeros(img.shape, dtype=np.uint8)
    contourImg = cv2.drawContours(contourImg, [contour], -1, 255, -1)

    # White pixels not common in both contour and circle will remain white 
    # else will become black.
    union_inter = cv2.bitwise_xor(circleImg, contourImg)
    
    # Finding ratio of the extent of overlap of contour to its enclosing circle. 
    # Smaller the ratio, more circular the contour.
    ratio = np.sum(union_inter == 255) / np.sum(circleImg == 255)
    
    # Storing only non circular contours(bacteria)
    if ratio > 0.55:
        finalContours.append(contour)

finalContours = np.asarray(finalContours)


# Finding center of bacteria and showing it.
bacteriaImg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

for bacteria in finalContours:
    M = cv2.moments(bacteria)
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])

    bacteriaImg = cv2.circle(bacteriaImg, (cx, cy), 5, (0, 0, 255), -1)
    
cv2.imshow("bacteriaImg", bacteriaImg)
cv2.waitKey(0)
注意:我仅拍摄右边的图像,并且图像的尺寸为(221,828)。如果输入的图像小于或大于此值,请调整腐 eclipse 和膨胀的迭代次数的值以相应地去除噪声,以获得良好的效果。
以下是输出图像:
1
2
3
同样,如您在第三幅图像中看到的,即最左边的细菌,其中心标记的位置不完全位于中心。之所以发生这种情况,是因为在代码中,我在一处使用了轮廓的凸包。您可以通过跟踪所有轮廓来解决此问题,然后最后取初始轮廓的中心。
我敢肯定,此代码也可以进行修改和改进,但这就是我现在能想到的。任何建议都将受到欢迎。

关于python - Python/OpenCV —在两个图像中匹配细菌的质心点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62982967/

相关文章:

python - 如何使用 sha-512 生成 hmac?

python - 如何使用opencv拍照并同时可视化网络摄像头

python - 执行 `from abc import xyz` 模块 `abc`去哪了?

java - OpenCV : Add/merge/combine 'only part' of Image A to Image B

python - 如何修复 python 3.7.1 上的导入 TensorFlow 错误?

python - Tkinter - 在禁用的文本框中拖动鼠标停止更新()

python - OpenCV calibrateCamera中的对象点和图像点

c++ - OpenCV 函数来计算类似于 MATLAB 产品的数组元素的乘积?

python - 从 python 抽象工厂中导入

python - 关键字参数和字典解包给出不同的结果