Image processing : detect high with camera - java

I have a camera that is pointing on a road. Right in boarder of this road, there is a big grey floor lamp. On this floor lamp i will paint some horizontal red lines.
I want to make a java application that can count the number of red lines.
I could simply get an image, with a for loop move on each pixel and show if it's red... but this will be really not optimized. I can specify that the lines are perpendicular to the image. To optimize I could simply move in y in the center of the image and count each time the color goes from gray to red?
do you have any idea of library that i can use, or an image processing process that make it better ?
thanx for help
EDIT :
From that image : image1
i can have this result : result
how coul'd i count the number of line

so at this moment i make some tries into my office.
Consider this wall is a floor lamp
on this picture you can see the calibrated pattern
And here you have the pattern used as overlay
Each line is separted with 5cm. when it snows, the bottom lines will gradually be hidden. So I can count the number of lines from the top to define the height of the snow.

Related

Get rectangle bounds for each letter in a image

So I'm trying to fill an ArrayList<Rectangle> with the bounds of each letter of an image file.
For example, given this .png image:
I want to fill an ArrayList<Rectangle> with 14 Rectangle(one rectangle for each letter)
We can assume that the image will contain only 2 colors, one for the background and one for the letters, in this case, pixels will be either white or red.
At first, I thought I could search for white columns in between the letters, then if I found a completely white column I could get for example the width by getting the lowest red pixel value and the highest red pixel value and width = maxX-minX and so on:
x = minX;
y = minY;
w = maxX-minX;
h = maxY-minY;
letterBounds.add(new Rectangle(x,y,w,h));
The problem is that there's no space in between the letters, not even 1 pixel:
My next idea was for each red pixel I find, look for a neighbor that hasn't been seen yet, then if I can't find a neighbor I have all the pixels to get the bounds of that letter. But with this approach, I will get 2 rectangles for letters like "i" I could then write some algorithm to merge those rectangles but I don't know how that will turn out with other multi part letters, and before I try that I wanted to ask here for more ideas
So do you guys have any ideas?
You can use the OpenCV cv2.findContours() function. Instead of using the cv2.drawcontours() function for drawing the contours, which will highlight the outline of the letter, you could instead draw a rectangle on the image by using the cv2.rectangle and by extracting the coordinates from cv2.findContours() function.
I think two step algorithm is enough to solve the problem if not using library like OpenCV.
histogram
seam calculation
1. histogram
C.....C..C...
.C.C.C...C...
. C.C....CCCC
1111111003111
dot(.) means background color(white)
C means any colors except background color(in your case, red)
accumulating the number of vertical pixels with non-background color generates histogram.
*
*
******..****
0123456789AB
It is clear the boundary exists at 6 and 7
2. seam calculation
Some cases like We, cannot be solved by histogram because there is no empty vertical lines at all.
Seam Carving algorithm gives us some hints
https://en.wikipedia.org/wiki/Seam_carving
More detail implementation is found at
princeton.edu - seamCarving.html
Energy calcuation for a pixel
The red numbers are not color values for pixels, but energy values calculated from adjacent pixels.
The vertical pathes with minimal energy give us the boundary of each characters.
3. On more...
Statistical data is required to determine whether to apply the seam carving or not.
Max and min width of characters
Even if histogram give us vertical boundaries, it is not clear there are two or more characters in a group.

find archery target in image of different perspectives

I'm trying to find a way to identify an archery target and all of its rings on a photo which might be made of different perspectives:
My goal is to identify the target and later on also where the arrows hit the target to automatically count their score. Presumptions are as follows:
The camera's position is not fixed and might change
The archery target might also move or rotate slightly
The target might be of different size and have different amount of circles
There might be many holes (sometimes big scratches) in the target
I have already tried OpenCV to find contours, but even with preprocessing (grayscale -> blur (-> threshold) -> edge detection) I still find a few houndred contours which are all distracted by the arrows or other obstacles (holes) on the target, so it is impossible to find a nice circular line. Using Hough to find circles doesn't work either as it will give me weired results as Hough will only find perfect circles and not ellipses.
With preprocessing the image this is my best result so far:
I was thinking about ellipse and circle fitting, but as I don't know radius, position and pose of the target this might be a very cpu consuming task. Another thought was about using recognition from a template, but the position and rotation of the target changes often.
Now I have the idea to follow every line on the image to check if it is a curve and then guess which curves belong together to form a circle/ellipse (ellipse because of the perspective). The problem is that the lines might be intersected by arrows or holes in a short distance so the line would be too short to check if it is a curve. With the smaller circles on the target the chance is high that it isn't recognised at all. Also, as you can see, circle 8, 7 and 6 have no clear line on the left side.
I think it is not neccessary to do perspective correction to achieve this task as long as I can clearly identify all the rings in the target.
I googled a long time and found some thesis which are all not exactly focussed on this specific task and also too mathematical for me to understand.
Is it by any chance possible to achieve this task? Could you share with me an idea how to solve this problem? Anything is very appreciated.
I'm doing this in Java, but the programming language is secondary. Please let me know if you need more details.
for starters see
Detecting circles and shots from paper target.
If you are using standardized target as on the image ( btw. I use these same too for my bow :) ) then do not cut off the color. You can select the regions of blue red and yellow pixels to ease up the detection. see:
footprint fitting
From that you need to fit the circles. But as you got perspective then the objects are not circles nor ellipses. You got 2 options:
Perspective correction
Use right bottom table rectangle area as marker (or the whole target). It is rectangle with known aspect ratio. so measure it on image and construct transformation that will change the image so it became rectangle again. There are tons of stuff about this: 3D scene reconstruction so google/read/implement. The basic are based just on De-skew + scaling.
Approximate circles by ellipses (not axis aligned!)
so fit ellipses to found edges instead circles. This will not be as precise but still close enough. see:
ellipse fitting
[Edit1] sorry did not have time/mood for this for a while
As you were unable to adapt my approach yourself here it is:
remove noise
you need to recolor your image to remove noise to ease up the rest... I convert it to HSV and detect your 4 colors (circles+paper) by simple tresholding and recolor the image to 4 colors (circles,paper,background) back into RGB space.
fill the gaps
in some temp image I fill the gaps in circles created by arrows and stuff. It is simple just scan pixels from opposite sides of image (in each line/row) and stop if hit selected circle color (you need to go from outer circles to inner not to overwrite the previous ones...). Now just fill the space between these two points with your selected circle color. (I start with paper, then blue,red and yellow last):
now you can use the linked approach
So find avg point of each color, that is approx circle center. Then do a histogram of radius-es and chose the biggest one. From here just cast lines out of the circle and find where the circle really stops and compute the ellipse semi-axises from it and also update the center (that handles the perspective distortions). To visually check I render cross and circle for each circle into the image from #1:
As you can see it is pretty close. If you need even better match then cast more lines (not just 90 degree H,V lines) to obtain more points and compute ellipse algebraically or fit it by approximation (second link)
C++ code (for explanations look into first link):
picture pic0,pic1,pic2;
// pic0 - source
// pic1 - output
// pic2 - temp
DWORD c0;
int x,y,i,j,n,m,r,*hist;
int x0,y0,rx,ry; // ellipse
const int colors[4]=// color sequence from center
{
0x00FFFF00, // RGB yelow
0x00FF0000, // RGB red
0x000080FF, // RGB blue
0x00FFFFFF, // RGB White
};
// init output as source image and resize temp to same size
pic1=pic0;
pic2=pic0; pic2.clear(0);
// recolor image (in HSV space -> RGB) to avoid noise and select target pixels
pic1.rgb2hsv();
for (y=0;y<pic1.ys;y++)
for (x=0;x<pic1.xs;x++)
{
color c;
int h,s,v;
c=pic1.p[y][x];
h=c.db[picture::_h];
s=c.db[picture::_s];
v=c.db[picture::_v];
if (v>100) // bright enough pixels?
{
i=25; // treshold
if (abs(h- 40)+abs(s-225)<i) c.dd=colors[0]; // RGB yelow
else if (abs(h-250)+abs(s-165)<i) c.dd=colors[1]; // RGB red
else if (abs(h-145)+abs(s-215)<i) c.dd=colors[2]; // RGB blue
else if (abs(h-145)+abs(s- 10)<i) c.dd=colors[3]; // RGB white
else c.dd=0x00000000; // RGB black means unselected pixels
} else c.dd=0x00000000; // RGB black
pic1.p[y][x]=c;
}
pic1.save("out0.png");
// fit ellipses:
pic1.bmp->Canvas->Pen->Width=3;
pic1.bmp->Canvas->Pen->Color=0x0000FF00;
pic1.bmp->Canvas->Brush->Style=bsClear;
m=(pic1.xs+pic1.ys)*2;
hist=new int[m]; if (hist==NULL) return;
for (j=3;j>=0;j--)
{
// select color per pass
c0=colors[j];
// fill the gaps with H,V lines into temp pic2
for (y=0;y<pic1.ys;y++)
{
for (x= 0;(x<pic1.xs)&&(pic1.p[y][x].dd!=c0);x++); x0=x;
for (x=pic1.xs-1;(x> x0)&&(pic1.p[y][x].dd!=c0);x--);
for (;x0<x;x0++) pic2.p[y][x0].dd=c0;
}
for (x=0;x<pic1.xs;x++)
{
for (y= 0;(y<pic1.ys)&&(pic1.p[y][x].dd!=c0);y++); y0=y;
for (y=pic1.ys-1;(y> y0)&&(pic1.p[y][x].dd!=c0);y--);
for (;y0<y;y0++) pic2.p[y0][x].dd=c0;
}
if (j==3) continue; // do not continue for border
// avg point (possible center)
x0=0; y0=0; n=0;
for (y=0;y<pic2.ys;y++)
for (x=0;x<pic2.xs;x++)
if (pic2.p[y][x].dd==c0)
{ x0+=x; y0+=y; n++; }
if (!n) continue; // no points found
x0/=n; y0/=n; // center
// histogram of radius
for (i=0;i<m;i++) hist[i]=0;
n=0;
for (y=0;y<pic2.ys;y++)
for (x=0;x<pic2.xs;x++)
if (pic2.p[y][x].dd==c0)
{
r=sqrt(((x-x0)*(x-x0))+((y-y0)*(y-y0))); n++;
hist[r]++;
}
// select most occurent radius (biggest)
for (r=0,i=0;i<m;i++)
if (hist[r]<hist[i])
r=i;
// cast lines from possible center to find edges (and recompute rx,ry)
for (x=x0-r,y=y0;(x>= 0)&&(pic2.p[y][x].dd==c0);x--); rx=x; // scan left
for (x=x0+r,y=y0;(x<pic2.xs)&&(pic2.p[y][x].dd==c0);x++); // scan right
x0=(rx+x)>>1; rx=(x-rx)>>1;
for (x=x0,y=y0-r;(y>= 0)&&(pic2.p[y][x].dd==c0);y--); ry=y; // scan up
for (x=x0,y=y0+r;(y<pic2.ys)&&(pic2.p[y][x].dd==c0);y++); // scan down
y0=(ry+y)>>1; ry=(y-ry)>>1;
i=10;
pic1.bmp->Canvas->MoveTo(x0-i,y0);
pic1.bmp->Canvas->LineTo(x0+i,y0);
pic1.bmp->Canvas->MoveTo(x0,y0-i);
pic1.bmp->Canvas->LineTo(x0,y0+i);
//rx=r; ry=r;
pic1.bmp->Canvas->Ellipse(x0-rx,y0-ry,x0+rx,y0+ry);
}
pic2.save("out1.png");
pic1.save("out2.png");
pic1.bmp->Canvas->Pen->Width=1;
pic1.bmp->Canvas->Brush->Style=bsSolid;
delete[] hist;

How to make a long shadow programmatically

I'm asking myself how to create a long shadow programmatically. Here its already working.
I would like to provide this functionality in a Java library (Android and maybe in JavaFX). What amazes me the most is the fact that the shadow creation works for a given text and also a image file.
If someone has any idea / advice how to get this working, please let me know, thanks in advance.
To draw black pixels in a loop which increments X and Y is the easiest part, I guess.
You have to define a line (red line, see Bresenham) and move the line across your whole image...
in my example: we move move horizontally
1) set the line to the very left (maybe even outside the visible scope).
2) set the line color to 'light'.
3) walk along each pixel from the line and draw the pixel with the line color. if the pixel hits a visible pixel (green rectangle), change the line color to 'shadow'
4) move the line one pixel to the right
5) if(not reached_right_border) goto 1
6) redraw text/image over the shadow

Draw curved custom object in LIBGDX?

I've recently been looking into LibGDX and seem to have hit a wall, seen in the picture, the blue dot represents the users finger, the map generation it self is where i seem to get stuck, does LibGDX provide a method of dynamically drawing curved objects? I could simply generate them myself as images but then the image is hugely stretched to the point of the gap for the finger can fit 3! But also would need to be 1000's of PX tall to accommodate the whole level design.
Is it such that i should be drawing hundreds of polygons close together to make a curved line?
On a side not i'll need a way of determining when the object has from bottom to top so i can generate another 'chunk' of map.
You don't need hundreds of polygons to make a curve like you drew. You could get away with 40 quads on the left, and 40 on the right, and it would look pretty smooth. Raise that to 100 on each side and it will look almost perfectly smooth, and no modern device is going to have any trouble running that at 60fps.
You could use the Mesh class to generate a procedural mesh for each side. You can make the mesh stay in one spot, locked to the camera, and modify it's vertices and UVs to make it look like you are panning down an infinitely long corridor. This will take a fair amount of math up front but should be smooth sailing once you have that down.
Basically, your level design could be based on some kind of equation that takes Y offset as an input. Or it could be a long array of offsets, and you could use a spline equation or linear equation to interpolate between them. The output would be the UV and X coordinates which can be used to update each of the vertices of your two meshes.
You can use the vertex shader to efficiently update the UV coordinates, using a constant offset uniform parameter that you update each frame. That way you don't have to move UV data to the GPU every frame.
For the vertex positions, use your Mesh's underlying float[] and call setVertices() each frame to update it. Info here.
Actually, it might look better if you leave the UV's and the X positions alone, and just scroll the Y positions up. Keep a couple quads of padding off top and bottom of screen, and just move the top quad to the bottom after it scrolls off screen.
How about creating a set of curved forms that can be put together variably. Like the gap in the middle will at the top and bottom of each image be in the middle (with the same curvature at end and beginning points)...
And inbetween the start and end points you can go crazy on the shape.
And finally, you can randomly put those images together and get an endless world.
If you don't want to stop in the middle each time, you could also have like three entry and exit points (left, middle, right)... and after an image that ends left, you of course need to add an image that starts left, but might end somewhere else...

Dividing the image and getting coordinates

I have an image with yellow background containing a random figure as shown in figure:
The random figure is divided by black lines into image pieces. Now each piece can be represented separately as a square containing that piece image with transparent background.
My question if it possible to find the coordinates of each piece algorithmically in the original image?
I am writing this application in Java.
I don't have much idea about the graphics. If its possible then please elaborate little bit.
Presuming the images look mostly like what you have here
Loop
Find a Red pixel
If found
flood fill red to non-red at this point, remembering region
create output image from this region
else
You are done
Use connected component labeling on the binary image (threshold your current image).
I used MATLAB to threshold the image, and run a labeling algorithm. Then I used region properties to find the centroid of each connected component (which are the image pieces you need). The following is the labeled image with the black stars representing the centroid of each piece:

Categories

Resources