I would like to determine an angle from an image (2D array).
I can get the coordinates of the point whose intensity is maximum with "unravel_index" and "argmax" but i would like to know how to get an another point whose intensity is high in order to calculate my angle.
I have to automatise that because i have a great number of images for post-treatement
So for the first coordinates, i can do that :
import numpy as np
from numpy import unravel_index
t = unravel_index(eyy.argmax(), eyy.shape)
And i need an another coordinates in order to calculate my angle...
t2 = ....
theta = np.arctan2(t[0]-t2[0],t[1]-t2[1])
What you could try is to look into the Hough Transform (Wikipedia - Hough Transform). The Hough Transform is a tool developed for finding lines and their orientation in images.
There is a Python implementation of the Hough Transform over at Rosetta Code.
I'm not sure if the lines in your data are distinct enough for the Hough Transform to yield good results but I hope it helps.
You can put your array in a masked array, find the pixel with the maximum intensity, then mask it, then find the next pixel with the maximum intensity.
Related
Assume that I have a binary numpy array (0 or 1 / True or False) that come from a .jpg image (2D array, from a grayscale image). I just made some processing to get the edges of the image, based on color change.
Now, from every surface/body from this array I need to get its centers.
Here the original image:
Here the processed one:
Now I need to get the centers of each surface generated for this lines (i.e. indexes that more or less point the center of each surface generated).
In the case you are interested, you can find the file (.npy) here:
https://gofile.io/d/K8U3ZK
Thanks a lot!
Found a solution that works. scipy.ndimage.label assigns a unique int. to each label or area, to validate the results I simply plot the output array
from scipy.ndimage import label
labeled_array, no_feats = label(my_binary_flower)
plt.imshow(labeled_array)
I'm very new to the image processing and object detection. I'd like to extract/identify the position and dimensions of teeth in the following image:
Here's what I've tried so far using OpenCV:
import cv2
import numpy as np
planets = cv2.imread('model.png', 0)
canny = cv2.Canny(planets, 70, 150)
circles = cv2.HoughCircles(canny,cv2.HOUGH_GRADIENT,1,40, param1=10,param2=16,minRadius=10,maxRadius=80)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv2.circle(planets,(i[0],i[1]),i[2],(255,0,0),2)
# draw the center of the circle
cv2.circle(planets,(i[0],i[1]),2,(255,0,0),3)
cv2.imshow("HoughCirlces", planets)
cv2.waitKey()
cv2.destroyAllWindows()
This is what I get after applying canny filter:
This is the final result:
I don't know where to go from here. I'd like to get all of the teeth identified. How can I do that?
I'd really appreciate any help..
Note that the teeth-structure is more-or-less a parabola (upside-down). If you could somehow guess the parabolic shape that defines the centroids of those blobs (teeth), then your problem could be simplified to a reasonable extent. I have shown a red line that passes through the centers of the teeth.
I would suggest you to approach it as follows:
Binarize your image (background=0, else 1). You could use sklearn.preprocessing.binarize.
Calculate the centroid of all the non-zero pixels. This is the central blue circle in the image. Call this structure_centroid. See this: How to center the nonzero values within 2D numpy array?.
Make polar slices of the entire image, centered at the location of the structure_centroid. I have shown a cartoon image of such polar slices (triangular semi-transparent). Cover complete 360 degrees. See this: polarTransform library.
Determine the position of the centroid of the non-zero pixels for each of these polar slices. See these:
find the distance between a point and a curve python.
Find the minimum distance from a point to a curve.
The array containing these centroids gives you the locus (path) of the average location of the teeth. Call this centroid_path.
Run an elimination/selection algorithm on the circles you were able to detect, that are closest to the centroid_path. Use a threshold distance to drop the outliers.
This should give you a good approximation of the teeth with the circles.
I hope this helps.
I need help on an algorithm I've been working. I'm trying to detect all the lines in a thresholded image, detect all the lines and then output only those that are parallel. The thresholded image outputs the object of my interest, and then I filter this image through a canny edge detector. This edge image is then passed through the Probabilistic Hough Transform. Now, I want the algorithm to be capable of detecting parallel lines in any image. I had in mind to do this by trying to detect the coordinates of all the lines and calculate their slope (with this then the angle). Parallel lines must have the same or almost the same angle and in that way I could output only the lines with the same angle. I could maybe draw an imaginary line in the image and then use it as reference for all the detected lines in the image? I just don't understand how to use the coordinates of all the lines detected through the function cv2.HoughLinesP(). The documentation of this functions says that the output is a 4D array and this is confusing for me. This is a part of my code:
Line Detection through Probabilistic Hough Transform
rho_res = .1 # [pixels]
theta_res = np.pi / 180. # [radians]
threshold = 50 # [# votes]
min_line_length = 100 # [pixels]
max_line_gap = 40 # [pixels]
lines = cv2.HoughLinesP(edge_image, rho_res, theta_res, threshold, np.array([]),
minLineLength=min_line_length, maxLineGap=max_line_gap)
Draw lines
if lines is not None:
for i in range(0, len(linesP)):
coords = lines[i][0]
slope = (float(coords[3]) - coords[1]) / (float(coords[2]) - coords[0])
cv2.line(img, (coords[0], coords[1]), (coords[2], coords[3]), (0,0,255), 2, cv2.LINE_AA)
Any idea on how I could extrapolate all the detected lines and then output only those that are parallel? I have tried a few algorithms online but none seems to work. Again, my problem is understanding and working with the output variables of the function cv2.HoughLinesP(). I have also find a code that is supposed to calculate the slope. I tried this but is just giving me one value (one slope). I want the slope of all the lines in the image.
Project the Hough transform onto the angle axis. This gives you a 1D signal as a function of theta, that is proportional to the “amount of line” in that orientation. Peaks in this signal indicate orientations that have many parallel lines. Find the largest peak, that gives you a theta.
Now go back to the Hough transform image, and detect peaks with this value of theta (maybe allow a little bit of wiggle). Now you’ll have all parallel lines at this orientation.
Sorry I can’t give you code that works with cv2.HoughLinesP, I don’t know this function. I hope this description gives you a starting point.
Calculate slope (angle) for all lines in range 0..Pi using atan2 function. To limit range by positive angles, add Pi to negative results.
Sort results by slope. Walk through sorted list, make unions for close values - these lines are near parallel. Note that you might have long series for slightly different neighbor value but start and end of series might differ a lot. So use some (angular) threshold to break series run.
I just don't understand how to use the coordinates of all the lines detected through the function cv2.HoughLinesP(). The documentation of this function says that the output is a 4D array and this is confusing for me.
4D array is just the output vector of detected lines. Each line is represented by a 4-element vector (x1, y1, x2, y2) , where (x1,y1) and (x2, y2) are the ending points of each detected line segment.
Please refer to the attached picture to get an idea of what those mean. Keep in my mind that those coordinated are in the image space.
I want to detect the rectangle from an image.
I used cv2.findContours() with cv2.convexHull() to filter out the irregular polygon.
Afterwards, I will use the length of hull to determine whether the contour is a rectangle or not.
hull = cv2.convexHull(contour,returnPoints = True)
if len(hull) ==4:
return True
However, sometimes, the convexHull() will return an array with length 5.
If I am using the criterion above, I will miss this rectangle.
For example,
After using cv2.canny()
By using the methods above, I will get the hull :
[[[819 184]]
[[744 183]]
[[745 145]]
[[787 145]]
[[819 146]]]
Here is my question: Given an array (Convex Hull) with length 5, how can I determine whether it is actually referring to a quadrilateral? Thank you.
=====================================================================
updated:
After using Sobel X and Y direction,
sobelxy = cv2.Sobel(img_inversion, cv2.CV_8U, 1, 1, ksize=3)
I got:
Well,
This is not the right way to extract rectangles. Since we are talking basics here, I would suggest you to take the inversion of the image and apply Sobel in X and Y direction and then run the findcontours function. Then with this you will be able to get lot of rectangles that you can filter out. You will have to apply lot of checks to identify the rectangle having text in it. Also I dont understand why do you want to force select rectangle with length 5. You are limiting the scale.
Secondly, another way is to use the Sobel X and Y image and then apply OpenCVs LineSegmentDetector. Once you get all the line segments you have to apply RANSAC for (Quad fit) so the condition here should be all the angles on a set of randomly chosen intersecting lines should be acute(roughly) and finally filter out the quad roi with text( for this use SWT or other reliable techniques).
As for your query you should select quad with ideally length 4 (points).
Ref: Crop the largest rectangle using OpenCV
This link will give you the jist of detecting the rectangle in a very simple way.
The images below give you a sort of walkthrough for inversion and sobel of image. Inversion of image eliminates the double boundaries you get from sobel.
For Inversion you use tilde operator.
Also before taking inversion also, its better you suppress the illumination artifacts. This can be done using homomorphic filtering. or taking log of an image.
It isn't so easy to fit a rectangle to a convex polygon.
You can try to find the minimum area or minimum perimeter rectangle by rotating calipers (https://en.wikipedia.org/wiki/Rotating_calipers).
Then by comparing the areas/perimeters of the hull and the rectangle, you can assess "rectangularity".
I'm using OpenCV's findHomography function (with RANSAC) in Python to find the transformation between two sets of points.
Looking at the documentation, the output is a mask and a transformation matrix.
The documentation is not clear about what the mask represents, and how the matrix is structured.
Is a 1 in the output mask a point that fits the found transformation or a point that was ignored?
And could you explain the makeup of the 3x3 output transformation matrix?
Thanks in advance and sorry if I missed some documentation which explains this.
Based on my limited search, mask returned by findHomography() has status of inliers and outliers, i.e. it's a matrix representing matches after finding the homography of an object.
This answer addresses your first question.
This answer addresses what a mask is and what are its dimensions.
Well what do you need to do with the mask? Because that field is not needed so you don't have to put any mask.
As for the resulting matrix. It is called a homography matrix, or H matrix and it represents the transformation of one point in an image plane to the same point in another image plane.
X1 = H * X2
The point X1 is the same point (X2) in a different plane.
So the H matrix is basically the description of how one point in, lets say, image 1 matches 1 point in image2.