I have a binary which has some text on different parts of the image like at the bottom, top, center, right middle center, etc.
Original Image
The areas I would like to focus on are the manually drawn regions shown in red.
I calculated the horizontal and vertical summations of the image and plotted them:
plot(sum(edgedImage1,1))
plot(sum(edgedImage1,2))
Can somebody give me explanation of what these plots are telling me about the original image with regards to the structure of which I explained above?
Moreover, how could these plots help me extracting those regions I just manually drew in red?
There's nothing sophisticated about the sum operation. Simply put, sum(edgedImage1,1) computes the sum of all rows for each column in the image and that is what you are plotting. Effectively, you are computing the sum of all non-zero values (i.e. white pixels) over all rows for each column. The horizontal axis in the plot denotes what row's sum you are observing. Similarly, sum(edgedImage,2) computes the sum of all columns for each row of the image and that is what you are plotting.
Because your text is displayed in a horizontal fashion, sum(edgeImage,1) won't be particularly useful. What is very useful is the sum(edgedImage,2) operation. For lines in your image that are blank, the horizontal sum of columns for each row of your image should be a very small value whereas for lines in your image that contain text or strokes, the sum should be quite large. A good example of what I'm talking about is seen towards the bottom of your image. If you consult between rows 600 and 700, you see a huge spike in your plot as there is a lot of text that is surrounded between those rows.
Using this result, a crude way to determine what areas in your image that contain text or strokes in your case would be to find all rows that surpass some threshold. Combined with finding modes or peaks from the sum operation that was just performed, you can very easily localize and separate out each region of text.
You may want to smooth the curve provided by sum(edgedImage,2) if you decide to determine how many blobs of text there are. Once you smooth out this signal, you will clearly see that there are 5 modes corresponding to 5 lines of text.
The second plot that shows the sum of each row. This can tell you in which rows you have a lot of information and in which you have none.
You can use this plot to find the rectangles by looking for a sharp incline in the value for a start of a rectangle and sharp decline in the value for the end of the rectangle. Before you do it i would low pass filter the data and then look at the derivative of this and look for a big derivative.
You can do the same the first plot but it is more sensitive.
The minimums in your last plot are the gaps between lines of text ...
You just take the graph and align its y axis to y axis of image and then Threshold areas with too small amount of pixels per column. These areas (Red) are the gaps between lines of Text or whatever you got on the image:
Now you should de-skew the image if needed. If the skew is too big you need to apply the de-skew even before the y axis summation.
De-skew operation characters in binary image (matlab)
After this you make the x axis summation plot for each non red region separately and in the same manner detect gaps between characters/words to get the area of each character for OCR. This time you align to x axis
These plots can be also used to OCR if taken on character region instead see
OCR and character similarity
If you do a statistical analysis of the gap/non gap sizes then the most recurrent one is usually the Font spacing/size for regular text.
Related
What I want to do is adjust the transparency of every pixel in a picture according to its ink ratio. I will take an example:
A node-link graph
In this picture, I want to calculate every pixel's ink ratio(That is, the ratio of the part covered by the line in each pixel to the size of the entire pixel).
Then assign a transparency value to each pixel according to this ratio, the higher the ratio is, the lower the transparency.
Finally,rendering the picture.
But now I don't know how to achieve it. Can someone help me or give me some advice to solve it? I will be very grateful!
I have very limited experience with any kind of image processing so these ideas may be far too simplistic to help.
In the simplest case if you are working on some kind of raw data AND with a single colour background (e.g. black line on white background) then any pixel values diverging from the background pixel value represent one or more lines passing through the pixel.
If this is not the case I think it's down to lots of calculations.
I suggest that first you have to calculate which pixels are covered in part or whole by one or more lines which depends on the line width and direction. I assume that the length and direction of each line is known so you can calculate one or more lines that
represent the boundaries of the line and use those to give the affected pixels.
Now it's necessary to calculate the proportion of the pixel that is covered by the total line i.e. the part of the pixel that lies between the calculated line boundaries. At this point I leave it to you - but I visualise a pixel as a square of known position and dimensions with a boundary line passing through it at known points to cut off a triangle or, for a horizontal or vertical line, a rectangle either within the line boundary or outside it.
Again - this assumes that the line width is greater than the diagonal of the pixel - if that is not so the calculation has to be done for both boundary lines.
That deals with one line passing through the pixel but of course multiple lines may have to be considered and the resultant value calculated.
If this is too simplistic and I have not understood the problem correctly I apologise.
I am writing a code that generate start and end points of strokes of a picture (Raster images) to let robot arm paint.
I have wrote an algorithm but with too many overlapping strokes:
https://github.com/Evrid/Painting-stroke-generation-for-robot-arm-or-CNC-machine
The input of my algorithm:
and the output (which is mirrored and re-assigned to the colors I have) with 50 ThresholdOfError (you can see the strokes are overlapping):
Things to notice are:
*The strokes needs to be none overlapping (if overlapping then have too many strokes)
*Painting have different colors, the same color better draw together
*The stroke size is like rectangles
*Some coloring area are disconnected, like below only yellow from a sun flower:
I am not sure which algorithm should I use, here is some possible ones I have thought about:
Method 1.Generate 50k (or more) random direction and position large size rectangles, if its area overlap the same color area and not overlapping other rectangles, then keep it, then decrease generated rectangle size and after a couple rounds keep decreasing again
Method 2.Extract certain color first then generate random direction and position large size rectangles (we have less area and calculation time)
Method 3.Do edge detection first, then rectangles are generated with direction along the edge, if its area overlap the same color area and not overlapping other rectangles, then keep it, then decrease generated rectangle size and after a couple rounds keep decreasing again
Method 4: Generate random circle, let the pen draw points instead (but may result too many points)
Any suggestions about which algorithm I should use?
I would start with:
Quantize your image to your palette
so reduce colors to your palette first see:
Effective gif/image color quantization?
Converting BMP image to set of instructions for a plotter?
segmentate your image by similar colors
for this you can use flood fill or growth fill to create labels (region index) in form of ROI
see Fracture detection in hand using image proccessing
for each ROI create infill path with thick brush
this is simple hatching you do this by generating zig zag like path with "big" brush width in major direction of ROI so use either AABB or OBB or PCA to detect major direction (direction with biggest size of ROI) and just AND it with polygon ROI
for each ROI create outline path with "thin" brush
IIRC this is also called contour extraction, simply select boundary pixels of selected ROI
then you can use A* on ROI boundary to sort the pixels into 2 halves (or more if complex shape with holes or thin parts) so backtrack the pixels and then reorder them to form a closed loop(s)
this will preserve details on boundary (while using infill with thick brush)
Something like this:
In case your colors are combinable you can use CMY color space and Substractive color mixing and process each C,M,Y channel separately (max 3 overlapping strokes) to have much better color match.
If you want much better colors you can also add dithering however that will slow down the painting a lot as it requires much much more path segments and its not optimal for plotter with tool up/down movement (they are better for printing heads or printing triggered without additional movements ...). To partially overcome this issue you could use partial dithering where you can specify the amount of dithering created (leading to less segments)
there are a lot of things you can improve/add to this like:
remove outline from ROI (to limit the overlaps and prevent details overpaint)
do all infills first and then all outlines
set infill brush width based on ROI size
adjust infill hatching pattern to better match your arm kinematics
order ROIs so they painted faster (variation of Traveling Sailsman problem TSP)
infill with more than just one brush width to preserve details near borders
Suggest you use the flood fill algorithm.
Start at top right pixel.
Flood fill that pixel color. https://en.wikipedia.org/wiki/Flood_fill
Fit rectangles into the filled area.
Move onto the next pixel that is not in the filled area.
When the entire picture has been covered, sort the rectangles by color.
I have an image which has plain dots scattered across. The dots are of the same size and they are solid (I can read the color to decide whether a point is inside or not). What is the most efficient algorithm to find the exact number of the dots?
I thought of Monte Carlo, but I don't know the sufficient number of random points that I should use. Any advice?
Edit: it's a white image that contains dots only.
This is good case for image processing algorithms.
For example, using OpenCV library, you could exploit the next approach:
If image format is color, convert it to gray scale (cvtColor)
Make image binary (pure black and white) with color inversion (cvThreshold with THRESH_BINARY_INV) to make white spots on the black background
Find connected components (findContours) - after that contours.size gives you number of dots
If you don't want to use any libraries, key point is connected components labeling
The simplest way to make CCL for small dots - using of Floodfill algorithm.
Make flood fill for background pixels, mark them with 0.
Scan through all pixels. When you meet unmarked one (at X,Y), start new flood fill with next marker value K (1,2 etc).
After each floodfill return to the next coordinate (X+1,Y) and continue scanning.
The last K value is the number of spots.
I have an image like this (thresholding, noise removal, etc. completed):
My final output should be an image without any of the jagged edges, and smaller than the given image. By this, I mean to say that the only difference between the 2 images must be that in the new one, the jagged edges must be removed, and not the jagged edges filled in. Like so (the final image must be the region within the red border, the red border is shown only for explanation):
I was thinking of something along the lines of using Hough transforms, or of using dilations and then erosions, but nothing seems to be working (probably my fault, because I have not worked in too much detail with them before).
Note that the language I'd like t do this in is MATLAB.
There are 2 primary aims to this:
To get the edges themselves, using Hough transforms
So that the 'Extrema' property returns the desired pints when using regionprops, like so:
The question, in a more concise form:
How would I go about extracting this T in MATLAB, such that it does not have rugged edges, but the overall figure is not larger than the original, as shown in the second figure above? In other words, what set of transformations (in MATLAB) would I use to smoothen the borders of the image with as little of the area lost as little as possible (but no area added) such that ruggedness disappears?
Is there a more efficient way of extracting the corner (extrema) points as shown in figure 2 above without requiring to go through step 1?
EDIT:
A few more sample images:
NB: All images in consideration will be composed of rectangles approximately at 90 to each other, and no other figure. So smoothening an image with a curved edge, for example, would be beyond the scope of an answer to this question (or even, for that matter, a trapezium, although I think that smoothening 2 straight edges should be the same, irrespective of whether the edge has another parallel to it or not).
Here are a few more images, for reference:
I'm not sure if my answer would satisfy your requirements. I'm putting it here because I think it's too long for a comment.
since you want the final output to be smaller than the input image, erode the input image. You can pick an appropriate kernel size.
perform a corner detection on this eroded image. This will give you all strong corners, but without any order
trace the boundaries of the eroded image. This should give you an ordered list of boundary pixels
now, with the help of these ordered boundary points you can order the corners that you found earlier
filter corner points that form approximately 90 degrees of angle. You can do this considering each 3 ordered corner points (two green points and the red point in between in the image below. It's just for illustration, not corner points that I calculated. At the end of this operation, you have all red points in the image below which are at strong corners, in addition to other yellow and green corner points)
now you can either find the equation of the line connecting 2 consecutive red points
or
fit a least-squares-line to the points between (and including) each 2 consecutive red points
since you did all this processing on a eroded image that is essentially smaller than the original image, you should get a smaller shape
Given a set of 2D points, I want to calculate a measure of how horizontally symmetrical and vertically symmetrical those points are.
Alternatively, for each set of points I will also have a rasterised image of the lines between those points, so is there any way to calculate a measure of symmetry for images?
BTW, this is for use in a feature vector that will be presented to a neural network.
Clarification
The image on the left is 'horizontally' symmetrical. If we imagine a vertical line running down the middle of it, the left and right parts are symmetrical. Likewise, the image on the right is 'vertically' symmetrical, if you imagine a horizontal line running across its center.
What I want is a measure of just how horizontally symmetrical they are, and another of just how vertically symmetrical they are.
This is just a guideline / idea, you'll need to work out the details:
To detect symmetry with respect to horizontal reflection:
reflect the image horizontally
pad the original (unreflected) image horizontally on both sides
compute the correlation of the padded and the reflected images
The position of the maximum in the result of the correlation will give you the location of the axis of symmetry. The value of the maximum will give you a measure of the symmetry, provided you do a suitable normalization first.
This will only work if your images are "symmetric enough", and it works for images only, not sets of points. But you can create an image from a set of points too.
Leonidas J. Guibas from Stanford University talked about it in ETVC'08.
Detection of Symmetries and Repeated Patterns in 3D Point Cloud Data.