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.
Related
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 am very new to Image processing and I am trying to cleanse pictures similar to picture 1 of the Black Pixels originating from the border of the Image.
The Images are clipped Characters from a PDF which I try to process with tesseract to retieve the character. I already searched in Stackoverflow for answers, but only found resolutions to get rid of black borders.
I need to overwrite all the black pixels from the corners with white pixels, so tesseract can correctly recognize the character.
I cannot alter the Bounding Boxes used to clip the Characters, since the characters are centered in different ares of the BoundingBox and if i Cut the BoundingBox, i would cut some Characters like seen below
My first guess would have been to recursively track down pixels with a certain threshhold of black in them, but I am scared of computing time in that case and wouldn't really know where and how to start, except for using two two-dimensional arrays, one with the pixels, and one with an indicator whether i already worked on that pixel or not.
Help would be greatly appreciated.
Edit: some more pictures of cases, where black pixels from the edge need to be cleared:
Edit: Code-Snippet to create Border Image:
#staticmethod
def __get_border_image(image: Image) -> Image:
data = numpy.asarray(image)
border = cv2.copyMakeBorder(data, top=5, bottom=5, left=5, right=5, borderType=cv2.BORDER_CONSTANT)
return Image.fromarray(border)
Try like this:
artificially add a 1px wide black border all around the edge
flood-fill with white all black pixels starting at top-left corner
remove the 1px border from the first step (if necessary)
The point of adding the border is to allow the white to "flow" all around all edges of the image and reach any black items touching the edge.
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.
Need to get rectangular shapes from a noisy color segmented image.
The problem is that sometimes the object isn't uniformly the correct color causing holes in the image, or sometimes reflection of the object in the background cause noise/false positive for the color segmentation.
The object could be in any position of the image and of any unknown rectangular size, the holes can occur anywhere inside the object and the noise could occur on any side of the object.
The only known constant is that the object is rectangular in shape.
Whats the best way to filter out that noise to the left of the object and get a bounding box around the object?
Using erosion would remove the detail from the bottom of the object and would cause the size of the bounding box to be wrong
I can't comment because of my rep, but I think you could try to analyse the colored image using other color spaces. Create a upper and a lower bound of the color you want until it selects the object, leaving you with less noise, which you can filter with erode/dilate/opening/closing.
For example, in my project I wanted to found a bounding box of a color-changing green rectangle, so I went and tried a lot of diferent color spaces with a lot of diferent upper/lower bounds until I finally got something worthy. Here is a nice read of what I'm talking about : Docs
You can also try filtering the object by área, after dilating it (you dilate first so the closer points connect to one another, while the more distant ones, which are the noise, don't, creating a big rectangle with lots of noise, but then you filter by a big área).
One method is to take histogram projection on both the horizontal and vertical axes, and select the intersection of ranges that have high projections.
The projections are just totals of object pixels in each row and each column. When you are looking for only one rectangle, the values indicated the probablity of the row/column belonging to the rectangle.
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.