我正在研究一种使用计算机视觉匹配细菌质心的算法。
因为我是计算机视觉的本科生和初学者,所以我没有专门针对此问题的代码。为了提供一些背景知识,我在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 2 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 和膨胀的迭代次数的值以相应地去除噪声,以获得良好的效果。以下是输出图像:
同样,如您在第三幅图像中看到的,即最左边的细菌,其中心标记的位置不完全位于中心。之所以发生这种情况,是因为在代码中,我在一处使用了轮廓的凸包。您可以通过跟踪所有轮廓来解决此问题,然后最后取初始轮廓的中心。
我敢肯定,此代码也可以进行修改和改进,但这就是我现在能想到的。任何建议都将受到欢迎。
关于python - Python/OpenCV —在两个图像中匹配细菌的质心点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62982967/