Rob Tucker
Rob Tucker

Reputation: 3

OpenCV - Draw only objects that keypoints refer to using python

I'm able to detect keypoints and descriptors

keypoints, des = surf.detectAndCompute(gray_image,None)

I'm able to draw keypoints

output_image = cv2.drawKeypoints(output_image, keypoints)

I'm able to locate keypoints from the image below that only correspond to text perfectly. I want to them copy the text onto a new image.

How can I draw only the objects the keypoints refer to?

source image

Here is the output of the keypoints keypoints only

Ultimately i want the keypoints only image to have the text instead of the keypoint markers

Upvotes: 0

Views: 3018

Answers (1)

Jeru Luke
Jeru Luke

Reputation: 21203

Do have a look at this approach. It is not so tidy but you can possibly refine it to suit your needs.

I obtained keypoints on the given image using cv2.ORB_create(), for which I obtained this:

img = cv2.imread(filename,0)
orb = cv2.ORB_create()
kp = orb.detect(img,None)
kp, des = orb.compute(img, kp)

img2 = cv2.drawKeypoints(img,kp,None,color=(0,255,0), flags=0)
cv2.imshow('keypoint_on_text.jpg', img2)

enter image description here

You can use surf for better detection of keypoints.

Then I obtained an image having a solid color(black in this case) having the same shape as that of the image. I drew these obtained keypoints on this black image.

mask = np.zeros((img.shape[0], img.shape[1], 3), np.uint8)
mask[:] = (0, 0, 0) 

fmask = cv2.drawKeypoints(mask,kp,None,color=(0,255,0), flags=0)
cv2.imshow('fmask.jpg', fmask)

enter image description here

Now I converted this to grayscale image and applied threshold to binarize it. I then found contours on this image and drew them with a bigger radius.

graymask = cv2.cvtColor(fmask,cv2.COLOR_BGR2GRAY)
ret, th = cv2.threshold(graymask, 50, 255, 0)
_, contours , _= cv2.findContours(th,2,1)
rep = cv2.drawContours(fmask, contours, -1, (0,255,0), 5)
cv2.imshow('contours.jpg',rep)

enter image description here

I converted this to greyscale, binarized it and masked it with the original image to finally obtain this:

repmask = cv2.cvtColor(rep,cv2.COLOR_BGR2GRAY)
ret, th1 = cv2.threshold(repmask, 50, 255, 0)
res = cv2.bitwise_and(img,img,mask = th1)
cv2.imshow('Only_Text.jpg',res)

enter image description here

As you can see, certain portions of the desired text is visible. If you use surf detection, you will be able to obtain more portion of text.

Upvotes: 2

Related Questions