I'm stumped. It's a simple white rectangle on a black background. Houghlines can't find the top line. It can find all the others, just not the top.
Anyone?
https://www.screencast.com/t/bNu4sptcS3a
Make sure that the top edge appears on the result of canny edge detection.
Dilate the image to make the edge fatter, so that it can get more votes
Make sure that the resolution of parameter rho is 1, so that the detector dos not miss the line. See here for a description on parameters.
Decrease the threshold value for voting, just in case. While the top and bottom lines are supposed to get equal number of votes, this might be different in practice.
The value of rho should be lower for the top horizontal line than the bottom horizontal line.
Related
I'm trying to detect the location of an approximately horizontal edge in my image.
Initially, I tried to accomplish this by just taking the column-wise maximum, but this turned out to be rather noisy and naive since the horizontally neighboring pixels are not taken into account.
y_edge = img.argmax(axis=1)
For example:
Where the edge becomes too vague, this algorithm just outputs noise.
My next approach was a Canny edge detector, used with a Gaussian blur (with a larger horizontal than vertical kernel) beforehand.
norm = [cv2.normalize(img, dst=None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U) for img in cropped_frames]
blur = [cv2.GaussianBlur(img, args.blur_kernel_size, 0) for img in norm]
edges = [cv2.Canny(img, *args.canny_thresholds, args.sobel_kernel_size, L2gradient=True) for img in blur]
After tweaking the parameters (normalisation, blurring, and thresholding), this generally performs a lot better because it operates in 2D and thus takes into account horizontally neighbouring pixels. This is an example of a frame where the edge is detected just as I like:
The small parts of the upper edge that are also detected is not a big problem, I can simply take the bottom edge for every column.
However, in some cases, when the edge becomes too vague in some places, the Canny edge detector misses the edge there. For example:
This is problematic for me. I would like to have an edge detected everywhere, horizontally, like my first algorithm does. In other words, I would ideally like to detect a single connected approximately horizontal edge, running through the full width of the image. That means:
Only a single horizontal edge per image (so no more than one detected pixel per column)
A detected edge for the full width of the image, so every column contains a detected pixel.
Is there another edge detection algorithm that is better for this problem? Or can I extend/modify the Canny-based approach I'm using now to satisfy my requirements?
If it matters, what I need in the end is the height (vertically) of the detected edge as a function of the horizontal distance.
I have a binary mask. In the binary image, I always have this mask which goes as horizontal band. I can use cv2.findContours() to find the boundary around the mask but I am only interested in the top line of mask as shown in the image https://i.stack.imgur.com/tZm1a.png (The line is hand drawn so it is not perfect). My question specifically is how to just draw the top line and not the lower part.
Using: OpenCV and Python
If you are able to detect both top and bottom parts of the object you want to detect, you can know which line is at the top by looking at their pixel position. You could apply a morphological gradient and cv2.connectedComponents() to have the two borders detected and then average their pixel positions to know which border is more at the top.
I do not know if your problem is in drawing the straight lines too, but I think it should be easy having the two points (left and right axis crossings) and then using cv2.line(image, start_point, end_point, color, thickness) in which the start_point and end_point are the limits of the top part of the mask.
If you post the original image, it should help even more.
Hope it works.
I'm trying to remove uneven white borders from different set of pictures. They all look like these:
What I'm doing right now is just drawing a rectangle around the picture in hope that it covers the white area:
h, w = img.shape
cv2.rectangle(img, (0,0), (w,h), (0,0,0), 2)
Depending on the picture it might work or not. As there are a variety number of pictures which are in similar situation I'm looking for a more logical solution which is applicable to all pictures with this kind of issue.
I think your way is right, but it's unaware whether it overlays figures (you may increase the thickness if you know there won't be figures with that margin) and the desired thickness is unknown.
You may use findContour. Find the "thick" figures (if you expect particular metrics as in the picture). Sort their extreme coordinates, add some margin and that would set the max depth of the border.
However then not a rectangle, but a line would be better drawn per each side, in case there are figures very close to the border.
Another scenario: first draw concentrating black rectangles (or lines per side) in order to clear the unevenness, then draw the white lines/rectangle with the desired thickness.
I want to connect the overhang (ridge) points of an image to create a separation between left and right.
The final output should look like this. Then I can identify them as 4 separate inner contours.
Is there a method to get the coordinates of the end points of overhangs (ridges) in order to draw a vertical line connecting them?
Or is there a better way to achieve this?
Use a Segment detector like this one
you'll get the start & end. Then decide which segments to connect based on some
criteria.
Note : (LSD is not supported since Opencv 4)
what you want is pretty customized which there might not be a common solution. And Im not sure you want to auto detect it or it is always a fixed pattern.
If it is a fixed pattern.
The first thing come to my mind is you auto crop 3 vertical section out. with each one like 10 pixel wide and 72 pixel tall. Then detect HARRIS corner point. Then for each corner point detected. draw a line in bettween the corner point. At least, overlay this patch into the original image. dada you have it
I was hoping to find out the number of pixels in a specific region from a pretty dark image , but cant find the right way. Can I please get some help.
I was trying to crop the image along the two red boundaries and then draw a white line over the red line and count nonzero pixels over it. But i think its a pretty ugly approach.
My end goal : It is to find the pixel to mm ratio (1 block between two red lines is 1.891mm)
P.S - It may sound a little silly to ask but i had a question too , if i zoom in to the image , does the number of pixels in a fixed region change than the original state(i believe they dont, not sure) while resizing does affects the number of pixels in a region right ?
Thank you so much in advance.
The red line stands out from the background. Pick its color and mark every pixel of a similar color. This should result in a binary image with only the scale.
Then follow the horizontal line from left to right, preferring horizontal moves over diagonal ones. Then determine the local width by means of vertical displacements. The maxima of the width will reveal the positions of the tick marks.
You can probably refine the measurements and resort to subpixel analysis, but this is another story.