user6189
user6189

Reputation: 683

Copy area inside contours to another image

I have the following code in Python to find contours in my image:

import cv2

im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

Now I want to copy the area inside the first contour to another image, but I can't find any tutorial or example code that shows how to do that.

Upvotes: 5

Views: 7370

Answers (2)

wwii
wwii

Reputation: 23783

Not familiar with cv2.findContours but I imagine that a contour is represented by an array of points with row/column (x/y values. If this is the case and the contour is a single pixel in width then there should be two points for every row - one each on the left and right extremes of the contour.

For each row in the contour
    *select* all the points in the image that are between the two contour points for that row
    save those points to a new array.

As @DanMašek points out, if the points in the contour array describe a simple shape with with only the ends, corners or breakpoints represented then you would need to fill in the gaps to use the method above.

Also if the contour shape is something like a star you would need to figure out a different method for determining if an image point is inside of the contour. The method I posted is a bit naive - but might be a good starting point. For a convoluted shape like a star there might be multiple points per row of the contour but it seems like the points would come in pairs and the points you are interested in would be between the pairs.

.

Upvotes: 0

avereux
avereux

Reputation: 607

Here's a fully working example. It's a bit overkill in that it outputs all the contours but I think you may find a way to tweak it to your liking. Also not sure what you mean by copying, so I'll assume you just want the contours outputted to a file.

We will start with an image like so (in this case you will notice I don't need to threshold the image). The script below can be broken down into 6 major steps:

  1. Canny filter to find the edges
  2. cv2.findContours to keep track of our contours, note that we only need outer contours hence the cv2.RETR_EXTERNAL flag.
  3. cv2.drawContours draws the shapes of each contour to our image
  4. Loop through all contours and put bounding boxes around them.
  5. Use the x,y,w,h information of our boxes to help us crop every contour
  6. Write the cropped image to a file.

import cv2

image = cv2.imread('images/blobs1.png')
edged = cv2.Canny(image, 175, 200)

contours, hierarchy = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(image, contours, -1, (0,255,0), 3)

cv2.imshow("Show contour", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

for i,c in enumerate(contours):
    rect = cv2.boundingRect(c)
    x,y,w,h = rect
    box = cv2.rectangle(image, (x,y), (x+w,y+h), (0,0,255), 2)
    cropped = image[y: y+h, x: x+w]
    cv2.imshow("Show Boxes", cropped)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    cv2.imwrite("blobby"+str(i)+".png", cropped)


cv2.imshow("Show Boxes", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Upvotes: 3

Related Questions