Having more control over the thinning algorithm? - algorithm

I have some text documents where I want to thin the text to varying widths such as 2 pixel wide strokes, 4 pixel wide and so on.
I know that matlab already has the thinning algorithm in bwmorph and one can get to the one pixel wide thinning by using
thinned = bwmorph(bw_image, 'thin', 'n=Inf');
But this thins the image to 1 pixel width. changing the value of n does not produce the desired result. Is there any way I could ensure thinning to n-pixel width?

You could always thin the characters first, then artificially expand their skeletons by performing morphology. For expanding, morphological dilation is most suitable. As such, thin the characters using the standard thinning algorithm, then dilate the result after using a suitable structuring element with a good size. The size of the structuring element should dictate how thick the thinned result is.
To further exemplify my point, here's an example with an image I found on Google:
Reading this in with MATLAB and converting to binary:
im = im2bw(imread('https://lh3.ggpht.com/aWaaZ-BsAXSYyyHRlube_NkiB-Q-FDx-Wpgg8qi5jqrNvAvNp87amEwSUNr7PdbCizY=w300'));
This is what we get:
Performing a thinning gives us:
thinned = bwmorph(im, 'thin', 'n=Inf');
If you want to increase the thickness of the thinning result so that the thickness is n pixels, use a basic square structuring element with size n x n and use this with the imdilate function, which performs morphological dilation on binary images. In general, to increase the thickness of the text to have an overall thickness of n pixels, you would choose the size of the square structuring element to be n.
Here are some examples of what I have discussed above.
n = 2
This would increase the thinning to be 2 pixels wide:
se = strel('square', 2);
expand = imdilate(thinned, se);
imshow(expand);
The function strel defines different structuring elements, but we will choose the square one via 'square' flag. Dilating the thinned image that you see above, we get:
n = 5
Simply change the structuring element to size to 5 x 5, and we get:
se = strel('square', 5);
expand = imdilate(thinned, se);
imshow(expand);
If you take any of the results and zoom into the text, you will see that the width of each stroke is indeed either 2 or 5 pixels. However, the assumption with the above code is that each character is sufficiently separated to allow the variable thickness of each stroke to be maintained. Should the characters be very close together, then dilation will merge these text characters together... but the thinning algorithm will most likely give you bad results even before dilation.

Related

Is there any known alg to fill certain area with rectangles of different size with most effective way?

By "effective way" I understand "with leaving more usable free areas for other rectangles".
I translating some game and I need to rebuild it's font. Font area is limited to certain size. I need to effectively fill that area with letters and letters combinations.
My current cycle increases X by 1 until we can place newly letter by that coords. If X hit font's right border, my cycle makes X = 0, Y++;
It leaves blank areas that is possible to use (marked with red):
How to use free space more effective?
Like that (at least):
I am assuming that the number of words in a row isn't very large(you said it's for some game). So you create a matrix say wordInfo[numberOfRowsInDisplay][maximumNumberOfColumnsForAnyRowInDisplay] you can calculate both of these variables by doing simple math like how many characters are in message(with width) and how many spaces(with width). It is filled as we go line by line and column by column for series of word/characters.
After that you for any wordInfo[row][column], represents width and height of that word/character. So if you populating some row you just see where this word/character ends(some number, say, pixel for example) and now check in previous row what was greatest height in this region including partial overlaps, and than set height of this word/character accordingly in wordInfo matrix, which will help in plotting next row. (It would be more efficient if you just only 2 rows in matrix, u got it?)
Note : if number of rows is large and there are man different height characters than in some cases might completely change.

Image Mean Normalization

I am wondering if I understood the mean normalization of images correctly.
As far as I know, you calculate the mean value over all pixels (lets assume it is in grayscale). Then, for each pixel, you subtract this mean value.
But how should one deal with negative values which could arise? For example, the whole image has a mean value of 100, but one specific pixel has an intensity of 90. After this normalization, the pixel's value would be -10.
This may not be quite what you're looking for but one option that avoids negative numbers in your output would be to normalize to the range of values present rather than to the image mean.
The equation would be: X' = (X - Xmin)/(Xmax - Xmin). This rescales the image to be between 0 and 1 (no negative values involved). If you'd like to save it as an easily view-able greyscale you could multiply values by 255 to rescale it.
It may also be worth noting that unless the entire image has a constant intensity, there is guaranteed to be some negative values after subtracting the mean (not simply a possibility that they could arise).
You don't have to deal with negative inputs, the model can handle them. It is good practice, for a Neural Network for example, to have inputs in the range [-1, 1]

Generating a discrete random subwindow from a given window

I'm working on an image processing application, and I have the problem that I'd like to generate a random subwindow from a given window. For instance, given a 5x5 (pixel) window, I would like to generate a subwindow in a given location in x,y with a given width and height. Currently, it's OK to assume that the width and height of the subwindow will always be equal to each other. The original window, however, does not have this constraint.
Currently, I'm just generating a random width/height for the subwindow that I know fits inside of the original window. Then I generate a valid x,y coordinate that allows that subwindow to fit within the original window. The problem with the current approach is that it doesn't respect the fact that smaller windows are much more plentiful and are therefore more likely to occur. By choosing a random dimension for the subwindow width/height, I'm assuming that their distribution in terms of width and height is uniform, when in fact it is not.
For instance, imagine we are given a 5x5 window. There are 25 possible 1x1 subwindows, 16 possible 2x2 windows, 9 possible 3x3 windows, 4 possible 4x4 windows, and 1 possible 5x5 window. Thus, I should choose a 1x1 window with a probability of about 0.45 (25/(25+16+9+4+1), a 2x2 window with a probability of about 0.29, etc.
I'm not sure how to quickly generate such allowable subwindows from the correct distribution without brute force evaluating all possible windows and then simply choosing one from the list, but I'm fairly sure there's a smarter approach to doing this, I just don't know where to begin.
Thanks!
For an n∙n window, there are (n-m+1)² sub-windows of size m∙m.
In general, for an x∙y window, there are (x-m+1)(y-m+1) sub-windows of size m∙m.
Suggested algorithm:
For each m, calculate the number of sub-windows; build an array of these values.
Sum the values in the array, and generate a uniformly-distributed integer in this range
Map this integer into the relevant sub-window size (using value-map or range-map)
Edit:
Actually you can do better.
There is 1 sub-window with width x, 2 sub-windows with width (x-1), ... , x sub-windows with width (x-(x-1)). In total, there are (1+2+3+...+x)= x(x+1)/2 possible options for width/horizontal-position.
Generate a uniformly-distributed integer r in the range [1, x(x+1)/2].
Determine the width using the following formula: w= x-floor( sqrt(2r-1.75)-0.5 )
Same for the height.
I am going to put this here even though it isn't quite right because my simulation shows that it is close-ish and perhaps we can work out what the flaw is. if it can't be fixed I will delete it:
1) Generate an Px discretely uninform on 1 to X
2) Generate a Py discretely uniform on 1 to Y
3) let Rx = X - Px + 1, let Ry = Y - Py + 1
4) Let A = Rx * Ry - the remaining area we can fill
5) Generate S discretely uniform on 1:min(Rx,Ry)
(Px,Py), (Px+S,Py),(Px,Py+S),(Px+S,Py+S) would define the coordinates of the region
Basically I just select the top left corner of the subregion and then randomly select an allowbale square subregion size given that my subregion starts at Rx, Ry position. The distribution of subregion size has the right diminishing shape, but it is too steep (100,000 iterations of 5x5):
1 2 3 4 5
0.60427 0.24523 0.10356 0.03875 0.00819

Implementing the intelligent recursive algorithm in matlab

Well am referring the following paper and trying to implement the algorithm as given in matlab
The only problem is how do i find a noisy pixel i.e Pixel with impulse noise?
X seems to be the impulse pixel in an image which i have to calculate
_
____________________________________________
Input – Noisy Image h
_______________________________________________
Step 1: Compute X
for every pixel repeat steps from 2 to 7
Step 2: Initialize w = 3
Step 3: If X(i,j) ≠ Impulse pixel
goto step 7
Step 4: ∆i,j = { h(i1,j1) | i-(w-1)/2 ≤ i1 ≤ i+(w-1)/2,
j-(w-1)/2 ≤ j1 ≤ j+(w-1)/2}
b=no. of black pixels in the window
w=no. of white pixels in the window
Step 5: If ∆i,j ≠ NULL
p(i,j) = mean(∆i,j
)
d(i,j) = | h(i,j) – p(i,j) |
else if (w < wmax)
w=w+2
goto step 4
else
if (b>w)
h(i,j)=0
else
h(i,j)=255
Step 7: Goto next pixel
Step 8: Calculate threshold t, from detailed coefficient
matrix d
for every pixel
Step 9: If (d(i,j)>t)
h(i,j)=p(i,j)
____________________________
Edit: To implement the PSM or the median filter method we
need to set some parameters and a threshold value. This
threshold value is dependent on the image and the noise
density. So, to restore different images we need to check for
a range of threshold values and find out the best one. So, in
our proposed algorithm we removed the need to define a threshold value. The algorithm is intelligent and determines
the threshold automatically.
The article you are trying to implement is obviously badly written...
For instance in the algorithm w means 2 things: the size of the window, and the number of white pixels!!!
Both the step 1 and 7, are refering to the same loop.
Anyway, to me, the "impulse pixels" are all the pixels a which are either equal to 0 or 255.
Basically, they are the pixels which are part of the "salt and pepper" noise.
So basically, you can find them by doing:
[impulsepixelsY,impulasPixelX]=find((im==0)|(im==255));
From the paper it seems that the "impulse pixels" are just the noisy pixels, in the case of salt & pepper noise. Furthermore, it also seems that the algorithm provides an "intelligent" mechanism to calculate the denoised value of a noisy pixel if its value is above a threshold (which it calculates adaptively).
So, what about "If X(i,j) ≠ Impulse pixel " ? Well, apparently, the authors assume to know (!) which pixels are noisy (!!), which makes the whole thing rather ridiculous, since this info is almost impossible to know.
I might also add that the rather stunning results presented in the paper are most probably due to this fact.
P.S. Regarding the argument that <"impulse pixels" are all the pixels a which are either equal to 0 or 255>, it is wrong. The set of pixels that have either 0 or 255 intensity value, includes the noisy pixels as well as proper pixels that just happen to have such a value. In this case, the algorithm will most probably collapse since it will denoise healthy pixels as well.

Finding image subsets between two images

I'm working on a way to handle hardware-based bitmap animation. As an input, I've got an image sequence of a simple bitmap (it's not a video, it's more like simple shapes, even though they might contain bitmap fills). I'm making a texture atlas of this animation (so it can be rendered quickly with GPU), and since this sequence sometimes has most part of it standing still while a small part of it is animating, I need an algorithm that can find the "common parts" between two images, so I can save memory.
The images might not have the same size (if an object is growing or shrinking, for example), so I need a way to detect the biggest common area between the two. I've seen this answer and it partly solves my problem. I'd like to know, though, if there is already a better algorithm for my case, specially because since the sizes can vary, one image is not necessarily contained within the other, but I'd need to find the common parts between the two.
One problem I see is that one image can be contained in many ways in another, how do you determine the right answer?
Does it have to be real-time? If not then you can do the simple O(n^4) search for it using a fitness function.
The fitness function could be the error between the images (which gives a n^8 algorithm).
UPDATE:
Wrong analysis of me sorry. The search is n^2 and the fitness function is n^2 which gives n^4.
The whole algorithm should look something like this:
w1 = width of image 1
w2 = width of image 2
h1 = height of image 1
h2 = height of image 2
for x = -w1 to w1+w2
for y = -h1 to h1+h2
find max fitness(x,y)
fitness(xc,yc){
m=0
for each x where image 1 overlaps image 2 displaced by xc
for each y where image 1 overlaps image 2 displaced by yc
if (image1[x][y] == image2[x+xc][y+yc])
m += 1
return m
}
UPDATE: Modified fitness function to find the number of overlaps, and then try to find the most overlaps.

Resources