将图像中的大对象装箱,其中包含图片中颜色相似且密度高的大小对象

Boxing large objects in image containing both large and small objects of similar color and in high density from a picture

对于我的研究项目,我试图区分水螅植物(较大的变形虫,看起来像橘子)和它们的丰年虾饲料(较小的橙色斑点),以便我们可以使用移液器自动清洁培养皿机器。来自培养皿机器的快照图像示例如下所示:

到目前为止,我已经应用了一个圆形蒙版和一个橙色蒙版 space 蒙版来创建一个干净的图像,因此它主要只是虾和九头蛇。

过滤后的图像中有一些残留的光伪影,但我不得不付出代价,否则我会失去非常薄的九头蛇的分辨率,例如原始图像的左上角。

我希望对较大的水螅植物进行装箱和标记,但找不到太多适用的文献来区分图像中具有相似属性的大物体和小物体,以实现我的目标。

我不想使用 ML 来解决这个问题,因为我没有足够的人力或足够大的数据集来制作一个好的训练集,所以我真的很感激一些更简单的视觉处理工具。如果我能知道一种更简单的方法来从已经清理过的图像中识别出更肿胀、更健康的水螅,那我就可以承受失去瘦水螅的代价。

我看过一些关于使用openCV的内容findCountours?我在正确的轨道上吗?

附件是我的代码,所以你知道我正在使用什么数据类型。

import cv2
import os
import numpy as np
import PIL

#abspath = "/Users/johannpally/Documents/GitHub/HydraBot/vis_processing/hydra_sample_imgs/00049.jpg"
#note we are in the vis_processing folder already
#PIL.Image.open(path)

path = os.getcwd() + "/hydra_sample_imgs/00054.jpg"
img = cv2.imread(path)
c_img = cv2.imread(path)

#==============GEOMETRY MASKS===================
# start result mask with circle mask

ww, hh = img.shape[:2]
r = 173
xc = hh // 2
yc = ww // 2
cv2.circle(c_img, (xc - 10, yc + 2), r, (255, 255, 255), -1)
hsv_cir = cv2.cvtColor(c_img, cv2.COLOR_BGR2HSV)

l_w = np.array([0,0,0])
h_w = np.array([0,0,255])
result_mask = cv2.inRange(hsv_cir, l_w, h_w)

#===============COLOR MASKS====================
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

#(hMin = 7 , sMin = 66, vMin = 124), (hMax = 19 , sMax = 255, vMax = 237)
# Threshold of orange in HSV space output from the HSV picker tool
l_orange = np.array([7, 66, 125])
h_orange = np.array([19, 255, 240])
orange_mask = cv2.inRange(hsv_img, l_orange, h_orange)
orange_res = cv2.bitwise_and(img, img, mask = orange_mask)

#===============COMBINE MASKS====================
for i in range(len(result_mask)):
    for j in range(len(result_mask[i])):
        if result_mask[i][j] == 255 & orange_mask[i][j] == 255:
            result_mask[i][j] = 255
        else:
            result_mask[i][j] = 0

c_o_res = cv2.bitwise_and(img, img, mask=result_mask)
cv2.imshow('res', c_o_res)
cv2.waitKey(0)
cv2.destroyAllWindows()

你走在正确的轨道上,但我必须说实话。没有深度学习,你会得到好的结果,但并不完美。

这就是我使用轮廓得到的结果:

代码:

import cv2
import os
import numpy as np
import PIL

#abspath = "/Users/johannpally/Documents/GitHub/HydraBot/vis_processing/hydra_sample_imgs/00049.jpg"
#note we are in the vis_processing folder already
#PIL.Image.open(path)

path = os.getcwd() + "/hydra_sample_imgs/00054.jpg"
img = cv2.imread(path)
c_img = cv2.imread(path)

#==============GEOMETRY MASKS===================
# start result mask with circle mask

ww, hh = img.shape[:2]
r = 173
xc = hh // 2
yc = ww // 2
cv2.circle(c_img, (xc - 10, yc + 2), r, (255, 255, 255), -1)
hsv_cir = cv2.cvtColor(c_img, cv2.COLOR_BGR2HSV)

l_w = np.array([0,0,0])
h_w = np.array([0,0,255])
result_mask = cv2.inRange(hsv_cir, l_w, h_w)

#===============COLOR MASKS====================
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

#(hMin = 7 , sMin = 66, vMin = 124), (hMax = 19 , sMax = 255, vMax = 237)
# Threshold of orange in HSV space output from the HSV picker tool
l_orange = np.array([7, 66, 125])
h_orange = np.array([19, 255, 240])
orange_mask = cv2.inRange(hsv_img, l_orange, h_orange)
orange_res = cv2.bitwise_and(img, img, mask = orange_mask)

#===============COMBINE MASKS====================
for i in range(len(result_mask)):
    for j in range(len(result_mask[i])):
        if result_mask[i][j] == 255 & orange_mask[i][j] == 255:
            result_mask[i][j] = 255
        else:
            result_mask[i][j] = 0

c_o_res = cv2.bitwise_and(img, img, mask=result_mask)

# We have to use gray image (1 Channel) to use cv2.findContours
gray = cv2.cvtColor(c_o_res, cv2.COLOR_RGB2GRAY)

contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

minAreaSize = 150
for contour in contours:
    if cv2.contourArea(contour) > minAreaSize:

        # -------- UPDATE 1 CODE --------
        # Rectangle Bounding box Drawing Option
        # rect = cv2.boundingRect(contour)
        # x, y, w, h = rect
        # cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
        
        # FINDING CONTOURS CENTERS
        M = cv2.moments(contour)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])
        # DRAW CENTERS
        cv2.circle(img, (cX, cY), radius=0, color=(255, 0, 255), thickness=5)
        # -------- END OF UPDATE 1 CODE --------

        # DRAW
        cv2.drawContours(img, contour, -1, (0, 255, 0), 1)


cv2.imshow('FinallyResult', img)

cv2.imshow('res', c_o_res)
cv2.waitKey(0)
cv2.destroyAllWindows()

更新 1:

要找到轮廓的中心,我们可以使用 cv2.moments。代码在 for 循环内用 # -------- UPDATE 1 CODE -------- 注释编辑。正如我之前提到的,这不是完美的方法,也许有一种方法可以改进我的答案,无需深度学习即可找到九头蛇的中心。