how to extract x,y coordinates from OpenCV "cv2.keypoint" object?
You can use:
import numpy as np
pts = np.float([key_point.pt for key_point in kp]).reshape(-1, 1, 2)
pts
will be an array
of keypoints.
OpenCV return keypoints coordinates and area from blob detection, Python
The pt
property:
keypoints = detector.detect(frame) #list of blobs keypoints
x = keypoints[i].pt[0] #i is the index of the blob you want to get the position
y = keypoints[i].pt[1]
Some documentation
How to get pixel coordinates from Feature Matching in OpenCV Python
We know that your keypoints are stored in kp1
and kp2
where they are lists of feature matches for the first and second image respectively. In the cv2.ORB
perspective, the feature descriptors are 2D matrices where each row is a keypoint that is detected in the first and second image.
In your case because you are using cv2.BFMatch
, matches
returns a list of cv2.DMatch
objects where each object contains several members and among them are two important members:
queryIdx
- The index or row of thekp1
interest point matrix that matchestrainIdx
- The index or row of thekp2
interest point matrix that matches
Therefore, queryIdx
and trainIdx
tell you which ORB features match between the first and second image. You'd use these to index into kp1
and kp2
and obtain the pt
member, which is a tuple of (x,y)
coordinates that determine the actual spatial coordinates of the matches.
All you have to do is iterate through each cv2.DMatch
object in matches
, append to a list of coordinates for both kp1
and kp2
and you're done.
Something like this:
# Initialize lists
list_kp1 = []
list_kp2 = []
# For each match...
for mat in matches:
# Get the matching keypoints for each of the images
img1_idx = mat.queryIdx
img2_idx = mat.trainIdx
# x - columns
# y - rows
# Get the coordinates
(x1, y1) = kp1[img1_idx].pt
(x2, y2) = kp2[img2_idx].pt
# Append to each list
list_kp1.append((x1, y1))
list_kp2.append((x2, y2))
Note that I could have just done list_kp1.append(kp1[img1_idx].pt)
and the same for list_kp2
, but I wanted to make it very clear on how to interpret the spatial coordinates. You could also go one step further and do a list comprehension:
list_kp1 = [kp1[mat.queryIdx].pt for mat in matches]
list_kp2 = [kp2[mat.trainIdx].pt for mat in matches]
list_kp1
will contain the spatial coordinates of a feature point that matched with the corresponding position in list_kp2
. In other words, element i
of list_kp1
contains the spatial coordinates of the feature point from img1
that matched with the corresponding feature point from img2
in list_kp2
whose spatial coordinates are in element i
.
As a minor sidenote, I used this concept when I wrote a workaround for drawMatches
because for OpenCV 2.4.x, the Python wrapper to the C++ function does not exist, so I made use of the above concept in locating the spatial coordinates of the matching features between the two images to write my own implementation of it.
Check it out if you like!
module' object has no attribute 'drawMatches' opencv python
How to manually set keypoints and extract features
Use the compute method in the orb API. Something standard would be
kp = orb.detect(img,None)
kp, des = orb.compute(img, kp)
But for your case, key points come from user input so use something like
input_kp = # comes from user
kp, des = orb.compute(img, input_kp)
Make sure that the input keypoints match the format that the compute method is expecting. You can create a key point from x, y values like this.
key_points = [cv2.KeyPoint(x1, y1, 1), cv2.KeyPoint(x2, y2, 1) ...]
How to obtain (x,y) coordinates of a shape found using mask in OpenCV, Python?
You can binarise image and then apply some morphological operations to get the proper connected components. Here is an approach. You can fine-tune this to get proper output.
import numpy as np
import cv2
import os
image=cv2.imread('path/to/image.jpg')
###binarising
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret2,th2 = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
###applying morphological operations to dilate the image
kernel=np.ones((3,3),np.uint8)
dilated=cv2.dilate(th2,kernel,iterations=3)
### finding contours, can use connectedcomponents aswell
_,contours,_ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
### converting to bounding boxes from polygon
contours=[cv2.boundingRect(cnt) for cnt in contours]
### drawing rectangle for each contour for visualising
for cnt in contours:
x,y,w,h=cnt
cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
Normal binary image
Dilated image
output with detected bounding boxes
Drawing SIFT keypoints
A simple solution may be: Iterating all keypoints and draw a "+" sign using cv2.drawMarker.
Here is a code sample:
import numpy as np
import cv2
def draw_cross_keypoints(img, keypoints, color):
""" Draw keypoints as crosses, and return the new image with the crosses. """
img_kp = img.copy() # Create a copy of img
# Iterate over all keypoints and draw a cross on evey point.
for kp in keypoints:
x, y = kp.pt # Each keypoint as an x, y tuple https://stackoverflow.com/questions/35884409/how-to-extract-x-y-coordinates-from-opencv-cv2-keypoint-object
x = int(round(x)) # Round an cast to int
y = int(round(y))
# Draw a cross with (x, y) center
cv2.drawMarker(img_kp, (x, y), color, markerType=cv2.MARKER_CROSS, markerSize=5, thickness=1, line_type=cv2.LINE_8)
return img_kp # Return the image with the drawn crosses.
img = cv2.imread("my_img.jpg")
sift = cv2.SIFT_create()
(keypoints, descriptors) = sift.detectAndCompute(img, None)
#img_kp = cv2.drawKeypoints(img, keypoints, cv2.DRAW_MATCHES_FLAGS_DEFAULT, color=(120,157,187))
img_kp = draw_cross_keypoints(img, keypoints, color=(120,157,187)) # Draw keypoints as "+" signs
cv2.imwrite("img.jpg", img_kp)
Sample result:
Crosses and circles - for testing:
As you can see, the "+" sings are at the centers of the circles.
How do I mask opencv's keypoints post detection?
According to this post, you need to iterate over all keypoints and descriptors and add the good ones to a new list.
There is no possibility to mark them unnecessary.
Here is a sample code:
import numpy as np
import cv2
some_image_file = 'graf.png'
image = cv2.imread(some_image_file)
rows, cols = image.shape[0], image.shape[1]
mask = np.full((rows, cols), 255, np.uint8) # cv2.imread(some_mask_file)
mask_2 = mask.copy() #cv2.imread(some_additional_mask_file)
mask_2[:, 0:cols//2] = 0
# Defining the detector:
detector = cv2.ORB_create(scoreType=cv2.ORB_FAST_SCORE)
# Detecting keypoints inside the initial mask's region:
kp, dsk = detector.detectAndCompute(image, mask)
good_kp = [] # List of "good keypoint"
good_dsk = [] # List of "good descriptors"
# Iterate over all keypoints and descriptors and the good ones to a new list.
# There is no possibility to mark them unnecessary.
# https://stackoverflow.com/questions/29180815/delete-matches-in-opencv-keypoints-and-descriptors
for k, d in zip(kp, dsk):
x, y = k.pt # Each keypoint as an x, y tuple https://stackoverflow.com/questions/35884409/how-to-extract-x-y-coordinates-from-opencv-cv2-keypoint-object
if mask_2[int(y), int(x)] != 0:
good_kp.append(k) # Append keypoint to a list of "good keypoint".
good_dsk.append(d) # Append descriptor to a list of "good descriptors".
# Draw keypoints for testing
image_kp = image.copy()
cv2.drawKeypoints(image, kp, image_kp)
image_good_kp = image.copy()
cv2.drawKeypoints(image, good_kp, image_good_kp)
cv2.imshow('image_kp', image_kp)
cv2.imshow('image_good_kp', image_good_kp)
cv2.waitKey()
cv2.destroyAllWindows()
Input image:
image_kp
:
image_good_kp.png
(left side keypoints are masked):
How to extract keypoints from Harris Corner Detector using Opencv
PythonThis is a how I wrote it in Python:
# convert coordinates to Keypoint type
eye_corner_keypoints = [cv2.KeyPoint(crd[0], crd[1], 13) for crd in eye_corner_coordinates]
# compute SIFT descriptors from corner keypoints
sift = cv2.xfeatures2d.SIFT_create()
eye_corner_descriptors = [sift.compute(gray,[kp])[1] for kp in eye_corner_keypoints]
C++Looking at the constructor signature in the OpenCV reference documentation for the KeyPoint class:
KeyPoint (float x, float y, float _size, float _angle=-1, float _response=0, int _octave=0, int _class_id=-1)
It looks like you can iterate through your coordinate points and instantiate your KeyPoint objects at each iteration (roughly) like so:
for (int i = 0; i < num_points; i++) {
KeyPoint kp(points_x[i], points_y[i], points_size[i]);
/* ... */
Warning: code is untested, I'm not a C++ programmer.
Pickling cv2.KeyPoint causes PicklingError
The problem is that you cannot dump cv2.KeyPoint to a pickle file. I had the same issue, and managed to work around it by essentially serializing and deserializing the keypoints myself before dumping them with Pickle.
So represent every keypoint and its descriptor with a tuple:
temp = (point.pt, point.size, point.angle, point.response, point.octave,
point.class_id, desc)
Append all these points to some list that you then dump with Pickle.
Then when you want to retrieve the data again, load all the data with Pickle:
temp_feature = cv2.KeyPoint(x=point[0][0],y=point[0][1],_size=point[1], _angle=point[2],
_response=point[3], _octave=point[4], _class_id=point[5])
temp_descriptor = point[6]
Create a cv2.KeyPoint from this data using the above code, and you can then use these points to construct a list of features.
I suspect there is a neater way to do this, but the above works fine (and fast) for me. You might have to play around with your data format a bit, as my features are stored in format-specific lists. I tried to present the above using my idea at its generic base. I hope that this may help you.
Related Topics
Convert a Tensor to Numpy Array in Tensorflow
Sqlalchemy: How to Join Several Tables by One Query
Get the First Item from an Iterable That Matches a Condition
How to Remove an Item from a List in Python If That Item Contains a Word
Get Value of Span Tag Using Beautifulsoup
How to Find Number of Ways That the Integers 1,2,3 Can Add Up to N
How to Loop Over Multiple Dataframes and Produce Multiple List
How to Save\Load Models in Spark\Pyspark
How to Set Automatically the Width of a Column in Xlsxwriter
How to Close Child Window in Tkinter
The Right Way to Limit Maximum Number of Threads Running At Once
Vary the Color of Each Bar in Bargraph Using Particular Value
How to Stop Execution of Python Script in Visual Studio Code
How to Replace Values At Specific Indexes of a Python List
How to Align Labels and Entry Boxes in a Gui Program
Changing Only One Row to Column in Python
How to Remove the Double Quote When the Value Is Empty in Spark