如何使用OpenCV裁剪图像,最多包含6个组织样本?

huangapple go评论72阅读模式
英文:

How to crop an image with upto 6 tissue samples using OpenCV?

问题

我有一个来自公共数据集的图像(示例如下)。我想使用工具将两个组织样本分开,以增加数据集中的实例数量。数据集中的其他图像最多有6个组织。是否可以使用OpenCV来实现这一点?也欢迎其他工具。

点击此处查看图像

我尝试过从一篇博客中找到的方法,但它只是在整个图像周围创建了一个边界框。也许阈值方案效果不好。

import cv2

# 读取输入图像
img = cv2.imread('pic.png')

# 将图像转换为灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 在灰度图像上应用阈值处理以创建二进制图像
ret, thresh = cv2.threshold(gray, 127, 255, 0)

# 查找轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 获取第一个轮廓
cnt = contours[0]

# 计算轮廓的边界矩形
x, y, w, h = cv2.boundingRect(cnt)

# 绘制轮廓
gray = cv2.drawContours(gray, [cnt], 0, (0, 255, 255), 2)

# 绘制边界矩形
gray = cv2.rectangle(gray, (x, y), (x+w, y+h), (0, 255, 0), 2)

# 显示带有绘制边界矩形的图像
cv2.imshow("Bounding Rectangle", gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
英文:

I have an image from a public dataset (sample show below). I want to separate the two tissue samples using a tool to increase the number of instances in the dataset. Other images in the dataset have upto 6 tissues. Is there I can do that using OpenCV? Other tools are also welcomed.

click here to view the image

I tried this from one of the blogs I came across but it just creates a bounding box around the entire image. Maybe the thresholding scheme doesn't work well

import cv2

# read the input image
img = cv2.imread('pic.png')

# convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# apply thresholding on the gray image to create a binary image
ret,thresh = cv2.threshold(gray,127,255,0)

# find the contours
contours, _ = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

# take the first contour
cnt = contours[0]

# compute the bounding rectangle of the contour
x,y,w,h = cv2.boundingRect(cnt)

# draw contour
gray = cv2.drawContours(gray,[cnt],0,(0,255,255),2)

# draw the bounding rectangle
gray = cv2.rectangle(gray,(x,y),(x+w,y+h),(0,255,0),2)

# display the image with bounding rectangle drawn on it
cv2.imshow("Bounding Rectangle", gray)
cv2.waitKey(0)
cv2.destroyAllWindows()

答案1

得分: 1

以下是翻译好的代码部分:

# 导入OpenCV库
import cv2

# 读取输入图像
img = cv2.imread('pic.png')

# 将图像转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 在灰度图上应用阈值处理以创建二值图像
# ret, thresh = cv2.threshold(gray, 127, 255, 0)
# ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)  # 反转极性 - findContours需要白色轮廓
ret, thresh = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV)  # 反转极性 - findContours需要白色轮廓

# 在cv2.findContours之前考虑添加形态学闭运算。

# 查找轮廓
# contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # 为什么使用灰度图?
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 使用RETR_EXTERNAL而不是RETR_TREE - 我们不想找到嵌套的轮廓,只需外部轮廓

# 取第一个轮廓
# cnt = contours[0]  # 为什么是第一个?第一个可能是微小的轮廓

gray_as_bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)  # 在绘制之前准备BGR图像

# 迭代所有轮廓
for cnt in contours:
    area = cv2.contourArea(cnt)  # 计算面积

    if area > 1000:  # 忽略像素少于1000的轮廓 - 被视为噪声。
        # 计算轮廓的边界矩形
        x, y, w, h = cv2.boundingRect(cnt)

        # 绘制轮廓
        gray_as_bgr = cv2.drawContours(gray_as_bgr, [cnt], 0, (0, 255, 255), 2)

        # 绘制边界矩形
        gray_as_bgr = cv2.rectangle(gray_as_bgr, (x, y), (x+w, y+h), (0, 255, 0), 2)  # 绘制绿色矩形

# 显示带有绘制的边界矩形的图像
cv2.imshow("thresh", thresh)
cv2.imshow("Bounding Rectangle", gray_as_bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()

这是您提供的代码的翻译部分。

英文:

There are multiple issues:

  • findContours expects white contours on black background - we have to invert polarity (and also select higher threshold):

     ret, thresh = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV)
    
  • contours, _ = cv2.findContours(gray is a bug - it should be contours, _ = cv2.findContours(thresh (find contours in thresh).

  • Use cv2.RETR_EXTERNAL instead of cv2.RETR_TREE - we don't want to find nested contours, only the outer contour:

     contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
  • cnt = contours[0] return the first contour that may be tiny, we have to iterate all contours.

  • We better filter contours by area - ignore small contours that are considered to be noise.


Code sample:

import cv2

# read the input image
img = cv2.imread('pic.png')

# convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# apply thresholding on the gray image to create a binary image
#ret, thresh = cv2.threshold(gray, 127, 255, 0)
#ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)  # Invert polarity - findContours expects white contours
ret, thresh = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV)  # Invert polarity - findContours expects white contours

# Consider adding morphological closing before cv2.findContours.

# find the contours
#contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)  # Why gray?
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # Use RETR_EXTERNAL instead of RETR_TREE - we don't want to find nested contours, only the outer contour

# take the first contour
#cnt = contours[0]  # Why the first? The fist may be a tiny contour

gray_as_bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)  # Prepare BGR image before drawing

# Iterate all contours
for cnt in contours:
    area = cv2.contourArea(cnt)  # Compute the area

    if area > 1000:  # Ignore contours with less than 1000 pixels - considered to be noise.
        # compute the bounding rectangle of the contour
        x, y, w, h = cv2.boundingRect(cnt)

        # draw contour        
        gray_as_bgr = cv2.drawContours(gray_as_bgr, [cnt], 0, (0, 255, 255), 2)

        # draw the bounding rectangle
        gray_as_bgr = cv2.rectangle(gray_as_bgr, (x, y), (x+w, y+h), (0, 255, 0), 2)  # Draw green rectangles

# display the image with bounding rectangle drawn on it
cv2.imshow("thresh", thresh)
cv2.imshow("Bounding Rectangle", gray_as_bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()

Output gray_as_bgr:
如何使用OpenCV裁剪图像,最多包含6个组织样本?

huangapple
  • 本文由 发表于 2023年6月8日 04:45:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76427003.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定