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

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

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

问题

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

点击此处查看图像

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

  1. import cv2
  2. # 读取输入图像
  3. img = cv2.imread('pic.png')
  4. # 将图像转换为灰度
  5. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  6. # 在灰度图像上应用阈值处理以创建二进制图像
  7. ret, thresh = cv2.threshold(gray, 127, 255, 0)
  8. # 查找轮廓
  9. contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
  10. # 获取第一个轮廓
  11. cnt = contours[0]
  12. # 计算轮廓的边界矩形
  13. x, y, w, h = cv2.boundingRect(cnt)
  14. # 绘制轮廓
  15. gray = cv2.drawContours(gray, [cnt], 0, (0, 255, 255), 2)
  16. # 绘制边界矩形
  17. gray = cv2.rectangle(gray, (x, y), (x+w, y+h), (0, 255, 0), 2)
  18. # 显示带有绘制边界矩形的图像
  19. cv2.imshow("Bounding Rectangle", gray)
  20. cv2.waitKey(0)
  21. 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

  1. import cv2
  2. # read the input image
  3. img = cv2.imread('pic.png')
  4. # convert the image to grayscale
  5. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  6. # apply thresholding on the gray image to create a binary image
  7. ret,thresh = cv2.threshold(gray,127,255,0)
  8. # find the contours
  9. contours, _ = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
  10. # take the first contour
  11. cnt = contours[0]
  12. # compute the bounding rectangle of the contour
  13. x,y,w,h = cv2.boundingRect(cnt)
  14. # draw contour
  15. gray = cv2.drawContours(gray,[cnt],0,(0,255,255),2)
  16. # draw the bounding rectangle
  17. gray = cv2.rectangle(gray,(x,y),(x+w,y+h),(0,255,0),2)
  18. # display the image with bounding rectangle drawn on it
  19. cv2.imshow("Bounding Rectangle", gray)
  20. cv2.waitKey(0)
  21. cv2.destroyAllWindows()

答案1

得分: 1

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

  1. # 导入OpenCV库
  2. import cv2
  3. # 读取输入图像
  4. img = cv2.imread('pic.png')
  5. # 将图像转换为灰度图
  6. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  7. # 在灰度图上应用阈值处理以创建二值图像
  8. # ret, thresh = cv2.threshold(gray, 127, 255, 0)
  9. # ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV) # 反转极性 - findContours需要白色轮廓
  10. ret, thresh = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV) # 反转极性 - findContours需要白色轮廓
  11. # 在cv2.findContours之前考虑添加形态学闭运算。
  12. # 查找轮廓
  13. # contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 为什么使用灰度图?
  14. contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 使用RETR_EXTERNAL而不是RETR_TREE - 我们不想找到嵌套的轮廓,只需外部轮廓
  15. # 取第一个轮廓
  16. # cnt = contours[0] # 为什么是第一个?第一个可能是微小的轮廓
  17. gray_as_bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) # 在绘制之前准备BGR图像
  18. # 迭代所有轮廓
  19. for cnt in contours:
  20. area = cv2.contourArea(cnt) # 计算面积
  21. if area > 1000: # 忽略像素少于1000的轮廓 - 被视为噪声。
  22. # 计算轮廓的边界矩形
  23. x, y, w, h = cv2.boundingRect(cnt)
  24. # 绘制轮廓
  25. gray_as_bgr = cv2.drawContours(gray_as_bgr, [cnt], 0, (0, 255, 255), 2)
  26. # 绘制边界矩形
  27. gray_as_bgr = cv2.rectangle(gray_as_bgr, (x, y), (x+w, y+h), (0, 255, 0), 2) # 绘制绿色矩形
  28. # 显示带有绘制的边界矩形的图像
  29. cv2.imshow("thresh", thresh)
  30. cv2.imshow("Bounding Rectangle", gray_as_bgr)
  31. cv2.waitKey(0)
  32. cv2.destroyAllWindows()

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

英文:

There are multiple issues:

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

    1. 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:

    1. 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:

  1. import cv2
  2. # read the input image
  3. img = cv2.imread('pic.png')
  4. # convert the image to grayscale
  5. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  6. # apply thresholding on the gray image to create a binary image
  7. #ret, thresh = cv2.threshold(gray, 127, 255, 0)
  8. #ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV) # Invert polarity - findContours expects white contours
  9. ret, thresh = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY_INV) # Invert polarity - findContours expects white contours
  10. # Consider adding morphological closing before cv2.findContours.
  11. # find the contours
  12. #contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Why gray?
  13. 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
  14. # take the first contour
  15. #cnt = contours[0] # Why the first? The fist may be a tiny contour
  16. gray_as_bgr = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) # Prepare BGR image before drawing
  17. # Iterate all contours
  18. for cnt in contours:
  19. area = cv2.contourArea(cnt) # Compute the area
  20. if area > 1000: # Ignore contours with less than 1000 pixels - considered to be noise.
  21. # compute the bounding rectangle of the contour
  22. x, y, w, h = cv2.boundingRect(cnt)
  23. # draw contour
  24. gray_as_bgr = cv2.drawContours(gray_as_bgr, [cnt], 0, (0, 255, 255), 2)
  25. # draw the bounding rectangle
  26. gray_as_bgr = cv2.rectangle(gray_as_bgr, (x, y), (x+w, y+h), (0, 255, 0), 2) # Draw green rectangles
  27. # display the image with bounding rectangle drawn on it
  28. cv2.imshow("thresh", thresh)
  29. cv2.imshow("Bounding Rectangle", gray_as_bgr)
  30. cv2.waitKey(0)
  31. 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:

确定