I have built a simple algorithm for visual mark detection with OpenCV on Python, that uses their ORB detector as the second step. I use ORB with the BFmatcher, the code is borrowed from this project: https://rdmilligan.wordpress.com/2015/03/01/road-sign-detection-using-opencv-orb/
The detection part in the code looks like this:
# find the keypoints and descriptors for object
kp_o, des_o = orb.detectAndCompute(obj,None)
if len(kp_o) == 0 or des_o == None: continue
# match descriptors
matches = bf.match(des_r,des_o)
Then there is a check on the number of feature matches, so it can tell if there is a match between the template image and the query. The question is: if yes, how do I get exact position and rotation angle of the found match?
The position is already known at this step. It is stored in variables x and y. To find the rotation, blur both template and the source, then either generate 360 rotated representations of the blurred template and then find the one that has the smallest difference with the region of interest or convert both images to polar coordinates and try to shift one of the images to achieve the best math (the shift will be the angle you want to rotate by).
Related
I have found the contour of the object through the function cv2.findContours and I want to know the coordinates where the contour changes slope relative to its front points, here I want that to be the starting point of the upper fin. . I would really appreciate it if you could give me a suitable suggestion. I hope you like this question
my input image : input image
image after apply threshold with value 195 : apply threshold
and i expect the result in like this : result
Perhaps you could try something like https://scikit-image.org/docs/stable/auto_examples/edges/plot_skeleton.html - maybe the resultant graph could have features indicating the location of the fin
I have several thousand images of fluid pathlines -- below is a simple example --
and I would like to automatically detect them: Length and position.
For the position a defined point would be sufficient (e.g. left end).
I don't need the full shape information.
This is a pretty common task but I did not find a reliable method.
How could I do this?
My choice would be Python but it's no necessity as long as I can export the results.
Counting curves, angles and straights in a binary image in openCV and python pretty much answers your question.
I tried it on your image and it works.
I used:
ret, thresh = cv2.threshold(gray, 90, 255, cv2.THRESH_BINARY_INV)
and commented out these two lines:
pts = remove_straight(pts) # remove almost straight angles
pts = max_corner(pts) # remove nearby points with greater angle
I am trying to locate QR position squares withing a QR code. QR position squares are the three boxes in the corners of a QR code:
I am template matching these to an image provided to me. I have discovered that there are significant 'ghosts' which appear in my output upon template matching:
Note the white region on the left is a giant smear of template, more distinct templates appear in black along the bottom but the whole image is essentially a smear of templates. Here is my code:
import cv2
import numpy as np
qrs=['A','B','C','D','E']
for qr in qrs:
template=cv2.imread(r'C:\Users\Matt\Desktop\Virginia Tech\CV\QR_Template_final.png',0)
img = cv2.imread(r'C:\Users\Matt\Desktop\Virginia Tech\CV\QR_'+qr+'.png', 0)
img_origin = cv2.imread(r'C:\Users\Matt\Desktop\Virginia Tech\CV\QR_'+qr+'.png')
# Binarize
img[img>125]=255
img[img<126]=0
img=img.astype(np.float32)
template=template.astype(np.float32)
# Template Matching
res=cv2.matchTemplate(img, template, cv2.TM_CCORR_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
res=255*(res-min_val)/(max_val-min_val)
out=cv2.imwrite(r'C:\Users\Matt\Desktop\Virginia Tech\CV\QR\Threshold\QR_IMG'+qr+'.png',img)
out=cv2.imwrite(r'C:\Users\Matt\Desktop\Virginia Tech\CV\QR\Threshold\QR_Threshold'+qr+'.png',res)
How do I address these ghosts?
I included a compressed version of the input. It is a picture of a QR code front and center in a grocery store without template any ghosts:
Also see this version of the output without binarization of the input:
Thanks so much for your help I have been stuck on this problem for some time.
You use wrong technique for dot detection. Template matching not have size and rotation robustness. The best way to solve your problem is to manually analyze each row of the image and find pattern: N black, N white, 2*N black, N white, N black. This is how real QR code detector works.
For implementation on C++ you can checkout this code. And here you can find some comments about algorithm.
There other way to find this dots. If you use some library for QR detection, this library can provide corners of QR code and you can calculate dot location.
I have the following code in python
import cv2
import numpy as np
def save_keypoints(image_path, type_image):
img = cv2.imread(image_path)
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
kp, descriptors =cv2.BRISK_create(10).detectAndCompute(gray,None)
mg=cv2.drawKeypoints(gray, kp, None,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imwrite('brisk_keypoints-'+ type_image+'.jpg',mg)
if __name__=="__main__":
save_keypoints("original.bmp" ,"original")
save_keypoints("fake600.bmp" ,"fake600")
save_keypoints("fake1200.bmp" ,"fake1200")
save_keypoints("fake2400.bmp" ,"fake2400")
Basically, the code will save an image with BRISK keypoints detected. However, here are the results of applying this code in four images:
Although the images are different (I can easily discriminate them using these BRISK descriptors in a bag of visual words approach), it seems that the keypoints detected in all these four images are visually the same or maybe the high number of concentric circles are confusing the viewer. How can I reduce the number of keypoints shown in such a way that I can see how these images are different through these descriptors?
The ideal answer would be as #Silencer suggested to filter the Keypoints. There are several ways you can achieve that. If you debug, you can see what information is contained in the ndarray Keypoints. The information should be something like this. So, using this, you can either sort the Keypoints based on the response (I'd suggest to start with that) or with the coordinates of the Keypoints. Response is basically how-good the Keypoint is, roughly speaking, how good is the corner-ness of the particular Keypoint.
For example:
Based on index
keypoints = detector.detect(frame) #list of keypoints
x = keypoints[i].pt[0] #i is the index of the Keypoint you want to get the position
y = keypoints[i].pt[1]
This you can use in a lamda expression (and not a loop) or a numpy function for fast optimization. Similarly, for response, you can do:
res = keypoints[i].response
I have seen responses from 31 to 320 for BRISK but you have to find the best value for your image.
Hope it helps!
I'm writing a script to process an image and extract a PDF417 2D barcode, which will then be decoded. I'm extracting the ROI without problems, but when I try to correct the perspective using cv2.warpPerspective, the result is not as expected.
The following is the extracted barcode, the red dots are the detected corners:
This is the resulting image:
This is the code I'm using for the transformation (the values are found by the script, but for the previous images are as follow):
box_or = np.float32([[23, 30],[395, 23],[26, 2141],[389, 2142]])
box_fix = np.float32([[0,0],[415,0],[0,2159],[415,2159]])
M = cv2.getPerspectiveTransform(box_or,box_fix)
warped = cv2.warpPerspective(img,M,(cols,rows))
I've checked and I don't find anything wrong with the code, yet the transformation is definitely wrong. The amount of perspective distortion in the extracted ROI is minimum, but may affect the decoding process.
So, is there a way to get rid of the perspective distortion? Am I doing something wrong? Is this a known bug or something? Any help is very much welcome.
BTW, I'm using OpenCV 3.3.0
It looks like you're giving the image coordinates as (y, x). I know the interpretation of coordinates varies within OpenCV.
In the homography example code they provide the coordinates as (x,y) - at least based on their use of 'h' and 'w' in this snippet:
h,w = img1.shape
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,M)
So try providing the coordinates as (x,y) to both getPerspectiveTransform and warpPerspective.