将图像中的大对象装箱,其中包含图片中颜色相似且密度高的大小对象
Posted
技术标签:
【中文标题】将图像中的大对象装箱,其中包含图片中颜色相似且密度高的大小对象【英文标题】:Boxing large objects in image containing both large and small objects of similar color and in high density from a picture 【发布时间】:2021-11-28 20:45:34 【问题描述】:对于我的研究项目,我试图区分水螅植物(看起来像橘子的较大变形虫)和它们的盐水虾饲料(较小的橙色斑点),以便我们可以使用移液器自动清洁培养皿。来自培养皿机器的快照示例如下所示:
到目前为止,我已经应用了一个圆形蒙版和一个橙色空间蒙版来创建一个经过清理的图像,因此它主要是虾和水螅。
过滤后的图像中会留下一些残留的光伪影,但我必须付出代价,否则我会失去原始图像左上角非常薄的 hydra 的分辨率。
我希望对较大的水螅植物进行装箱和标记,但找不到太多适用的文献来区分图像中具有相似属性的大小对象,以实现我的目标。
我不想使用 ML 来解决这个问题,因为我没有人力或足够大的数据集来制作一个好的训练集,所以我真的很感谢一些更简单的视觉处理工具。如果我能知道一种更简单的方法来从已经清理的图像中识别出更丰满、更健康的 hydra,我可以承受失去瘦身 hydra 的损失。
看过一些关于使用openCVfindCountours
的内容?我在正确的轨道上吗?
附上我的代码,以便您知道我正在使用的数据类型。
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()
【问题讨论】:
findContours
,然后使用contourArea
过滤。这只适用于不接触/重叠的对象。您可能还需要一些形态学操作(腐蚀/扩张/打开/关闭)。
顺便说一句,假设两者都是掩码(仅包含 0 和 255),那么双循环可以替换为 result_mask &= orange_mask
——python 语法:if 表达式中的 &
(整数)应该是 and
(布尔值)
谢谢 Christoph,会注意双 for 循环。
【参考方案1】:
你是在正确的轨道上,但我必须诚实。如果没有深度学习,您将获得好的结果,但并不完美。
这就是我使用轮廓得到的结果:
代码:
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 --------
注释进行了编辑。正如我之前提到的,这不是完美的方法,也许有一种方法可以改进我的答案,在没有深度学习的情况下找到九头蛇的中心。
【讨论】:
知道了,感谢您的建议和代码。需要注意的是,我需要从字面上“装箱”九头蛇以获得移液器的 x y 坐标。虽然轮廓突出了 hydra 所在的位置,但有没有办法显示找到的轮廓的“中心”? @JohannPally 如果您对我的回答感到满意,我想通过回答旁边的“V”号按钮(左侧)获得确认回答,我不确定您是否知道关于那个。关于轮廓的中心,我已经为您更新了我的答案,但您可以尝试提出一个新问题(在新帖子中),也许有人可以改进我的答案。祝你好运!! 感谢罗伊的帮助!以上是关于将图像中的大对象装箱,其中包含图片中颜色相似且密度高的大小对象的主要内容,如果未能解决你的问题,请参考以下文章