Reputation: 545
I am working with images with objects in it. I used canny edge detection and contours to detect and draw the edges of the objects in it. Then I used both SIFT and SURF to detect key points in the object. Here is the sample code I've been working on.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread(image)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 100,200)
image, contours, hierarchy = cv.findContours(edges, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
outimg = cv.drawContours(img, contours, -1, (0,255,0), 3)
sift = cv.xfeatures2d_SIFT.create()
kp, des = sift.detectAndCompute(outimg,None)
Is there any way to remove the key points that are on the edge? Answer with example will be really helpful. Thanks.
Upvotes: 0
Views: 1258
Reputation: 10850
You can use pointPolygonTest method to filter detected keypoints. Use detected contours as boundary polygon. You will also be able to define desired margin.
Simaple example (fot 4 point contour):
def inside_point(self, point, rect):
# point is a list (x, y)
# rect is a contour with shape [4, 2]
rect = rect.reshape([4, 1, 2]).astype(np.int64)
dist = cv2.pointPolygonTest(rect,(point[0], point[1]),True)
if dist>=0:
# print(dist)
return True
else:
return False
You can also draw contours on mask image and to check if the point is inside contours, just check the pixel value with the point coordinates, and if it not 0 then point is valid.
Seems everythig woeks fine: I have no xfeatures2d, so used ORB features here.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('image.jpg')
#img = cv.resize(img,(512,512))
img = cv.copyMakeBorder(img,20,20,20,20, 0)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
_ , gray = cv.threshold(gray,20,255,cv.THRESH_TOZERO)
gray=cv.erode(gray,np.ones( (5,5), np.int8) )
edges = cv.Canny(gray, 100,200)
contours, hierarchy = cv.findContours(edges, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
orb = cv.ORB_create(nfeatures=10000)
kp, des = orb.detectAndCompute(gray,None)
outimg = cv.drawContours(img, contours, -1, (0,255,0), 3)
k = []
for cont in contours:
for i in kp:
(x, y) =i.pt
dist = cv.pointPolygonTest(cont, (x,y), True)
if dist>=0:
k.append(i)
for i in k:
pt=(int(i.pt[0]),int(i.pt[1]) )
cv.circle(outimg,pt,3, (255,255,255),-1)
cv.imwrite('result.jpg',outimg)
cv.imshow('outimg',outimg)
cv.waitKey()
Upvotes: 1
Reputation: 545
I am still finding it difficult to remove key points from the given image. I tried to append the key points in a new list if it's not in the contour but shows an error when I use cv2.drawKeypoints function because the new list is not of type keypoint. This is the work I have done so far.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread(image)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
edges = cv.Canny(gray, 100,200)
image, contours, hierarchy = cv.findContours(edges, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
outimg = cv.drawContours(img, contours, -1, (0,255,0), 3)
sift = cv.xfeatures2d_SIFT.create()
kp, des = sift.detectAndCompute(outimg,None)
k = cv.KeyPoint()
for i in kp:
(x, y) =i.pt
dist = cv.pointPolygonTest(contours[0], (x,y), True)
if dist>=0:
k1.append(k)
Upvotes: 1