最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

python - OpenCV drawContours fills "inner" contours - why? - Stack Overflow

programmeradmin1浏览0评论

I use OpenCV findContours() to extract contours, which I then draw in a figure. The contours themselves sometimes enclose holes. When using drawContours(), these holes are not drawn, but filled instead. I am using the full hierarchy, but do I also need to pass that hierarchy into the drawContours function somehow?

import cv2
import numpy as np
import matplotlib.pyplot as plt

f = "file"
width = 853
height = 418

img = cv2.imread(f,-1)

roi = np.zeros(img.shape[:2], np.uint16)
roi = cv2.rectangle(roi, (13,78), (width,height), 65535, cv2.FILLED)
mask = cv2.bitwise_and(roi, img)

threshold = 350

ret, th1 = cv2.threshold(mask,threshold,255,cv2.THRESH_BINARY)

contour,hier = cv2.findContours(th1.astype(np.uint8),cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
canvas = np.zeros(img.shape[:2], np.uint8)
canvas2 = np.zeros(img.shape[:2], np.uint8)

for cnt in contour:
    cv2.drawContours(canvas,[cnt],0,255,2)
    cv2.drawContours(canvas2,[cnt],0,255,-1)

fig, ax = plt.subplots(3,1)
ax[0].imshow(img, 'gray')
ax[1].imshow(canvas, 'gray')
ax[2].imshow(canvas2, 'gray')

Which produces the following results

How can I prevent the inner contours from being filled?

I use OpenCV findContours() to extract contours, which I then draw in a figure. The contours themselves sometimes enclose holes. When using drawContours(), these holes are not drawn, but filled instead. I am using the full hierarchy, but do I also need to pass that hierarchy into the drawContours function somehow?

import cv2
import numpy as np
import matplotlib.pyplot as plt

f = "file"
width = 853
height = 418

img = cv2.imread(f,-1)

roi = np.zeros(img.shape[:2], np.uint16)
roi = cv2.rectangle(roi, (13,78), (width,height), 65535, cv2.FILLED)
mask = cv2.bitwise_and(roi, img)

threshold = 350

ret, th1 = cv2.threshold(mask,threshold,255,cv2.THRESH_BINARY)

contour,hier = cv2.findContours(th1.astype(np.uint8),cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
canvas = np.zeros(img.shape[:2], np.uint8)
canvas2 = np.zeros(img.shape[:2], np.uint8)

for cnt in contour:
    cv2.drawContours(canvas,[cnt],0,255,2)
    cv2.drawContours(canvas2,[cnt],0,255,-1)

fig, ax = plt.subplots(3,1)
ax[0].imshow(img, 'gray')
ax[1].imshow(canvas, 'gray')
ax[2].imshow(canvas2, 'gray')

Which produces the following results

How can I prevent the inner contours from being filled?

Share Improve this question edited Feb 3 at 11:31 DozerD asked Feb 3 at 11:29 DozerDDozerD 73 bronze badges 4
  • what happens if you use cv2.drawContours(canvas2,[cnt],0,255,2) ? I suspect that using -1 will fill the contour. – DrBwts Commented Feb 3 at 12:34
  • I want the contours to be filled, but only the actual contours and not the holes confined between contours. – DozerD Commented Feb 3 at 13:01
  • Look for something called "winding rules" in the documentation. – Mark Ransom Commented Feb 3 at 13:04
  • please share the input image to test – sturkmen Commented Feb 3 at 13:35
Add a comment  | 

1 Answer 1

Reset to default 0

Looking at bit more into the hierarchy structure I found that all top-level contours have value -1 in the third entry. This is how I finally got what I wanted:

import cv2
import numpy as np
import matplotlib.pyplot as plt

path = "f"
pixelSize = 0.1172
pixelArea = pixelSize*pixelSize
sliceThickness = 0.75
width = 853
height = 420
area = width*height*pixelArea

img = cv2.imread(f,-1)

roi = np.zeros(img.shape[:2], np.uint16)
roi = cv2.rectangle(roi, (13,76), (width,height), 65535, cv2.FILLED)
mask = cv2.bitwise_and(roi, img)

threshold = 350

ret, th1 = cv2.threshold(mask,threshold,255,cv2.THRESH_BINARY)

contour,hier = cv2.findContours(th1.astype(np.uint8),cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
canvas = np.zeros(img.shape[:2], np.uint8)
canvas2 = np.zeros(img.shape[:2], np.uint8)
neg = np.zeros(img.shape[:2], np.uint8)
fin = np.zeros(img.shape[:2], np.uint8)

for cnt, hr in zip(contour, hier[0]):
    if hr[3] != -1:
        cv2.drawContours(neg,[cnt],0,255,-1)
    cv2.drawContours(canvas,[cnt],0,255,2)
    cv2.drawContours(canvas2,[cnt],0,255,-1)
    fin = canvas2-neg

fig, ax = plt.subplots(5,1)
ax[0].imshow(img, 'gray')
ax[1].imshow(canvas, 'gray')
ax[2].imshow(canvas2, 'gray')
ax[3].imshow(neg, 'gray')
ax[4].imshow(fin, 'gray')      

And the result.

发布评论

评论列表(0)

  1. 暂无评论