Adding Offset to 'contours'

Viewed 105

I'm working in Windows 10, with Python 3.8 and OpenCV 4.5, and creating an artificial dataset to train a Convolutional Neural Network. In one step I need to translate a contour structure, but I'm stucked at this problem and I can't fix.

I need to translate a contour by x_offset and y_offset. But I'm having a hard time with np.array types and the way OpenCV organize contours.

I read in the OpenCV docs (findContours()) that contours are stored as vectors, this shows us that these points need to be arranged somehow, and on my tries I'm probably losing the arrangement, because I'm getting this error:

error: OpenCV(4.5.3) :-1: error: (-5:Bad argument) in function 'drawContours'
> Overload resolution failed:
>  - contours is not a numpy array, neither a scalar
>  - Expected Ptr<cv::UMat> for argument 'contours'

So I went to a much simpler file and recreated the first example on that Getting Started with Contours site:

import numpy as np
import cv2

im = cv2.imread('test.jpg',cv2.IMREAD_COLOR)
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for data in contours:
    print (f"The contours have this data: {data}")
cv2.drawContours(im,contours,-1,(0,255,0),3)
cv2.imshow('output',im)
cv2.waitKey(0)

Square Recognized in Binary Image

When I print contours, I get this as result:

[array([[[207, 146]],

       [[207, 455]],

       [[603, 455]],

       [[603, 146]]], dtype=int32)]

I'm trying to keep the structure, but remap the points using x_offset and y_offset, so my result should be something like:

[array([[[207 + x_offset, 146 + y_offset]],

       [[207 + x_offset, 455 + y_offset]],

       [[603 + x_offset, 455 + y_offset]],

       [[603 + x_offset, 146 + y_offset]]], dtype=int32)]

Contour with Offset

Can someone help with an algorithm to perform this operation without losing the structure of the contour? So I can use drawContours to draw this translated contour.

1 Answers

You just have to add your X and Y offset to every contour as a tuple:

x_offset, y_offset = 5, 3
for contour in contours:
  # contour with new offset is created
  new_contour = contour + (x_offset, y_offset)
  # draw the new contour on the image
  cv2.drawContours(im,new_contour,-1,(0,255,0),3)

I guess the data structure of contours got you confused. contours is a tuple. Every contour identified is stored as an individual tuple. The points for each contour is stored inside these tuples.

Related