# Recognize shapes from pictures

• 06-19-2011, 11:03 PM
acole5
Recognize shapes from pictures
Hello, I'm currently working on a project that asks us to "Identify the number of shapes in each image and the type for each shape". The image backgrounds are white and the shapes are black. Some of the images have only one shape in them while others have two. I've coded the program to recognize the shape names for the images with only one shape in them but I'm having trouble identifying when there is more than one shape. Here's the link to the full assignment along with the images we should be using: http://people.uncw.edu/tompkinsj/121...ThatShape.html

This is my program so far (it identifies each shape correctly when it's the only shape in the image):
Code:

```import algoritharium.*; import java.awt.Color; public class Shapes {         public static void main(String[] args) {                 new ImageViewer();         }         public static void identifyShape() {         Image img = ImageViewer.getImage();         Color[][] c = img.getPixelColors();         recolor(c);         int rowCount=0;         int row=0;         int rowTotal=0;         //Number of rows with black pixels         for(int q=0; q<img.getWidth(); q++){                 for(int w=0; w<img.getHeight(); w++) {                         while(c[q][w]==Color.BLACK && w<(img.getHeight())) {                                 row++;                                 w++;                         }                         if (row>rowTotal)                                 rowTotal=row;                         row=0;           }         }         double blackPixels[]=new double [rowTotal];         int arrayNumber=0;         //Number of black pixels per row         for(int y=0; y<img.getHeight(); y++){                 for(int x=0; x<img.getWidth(); x++) {                         if(c[x][y]==Color.BLACK)                         //while (c[x][y]==Color.BLACK&&x<img.getWidth()){                                 rowCount++;                                 //x++;                         }                 if (rowCount>0){                         blackPixels[arrayNumber]=rowCount;                         arrayNumber++;                         rowCount=0;                 }         }         double maxB= max(blackPixels);         double meanB= mean(blackPixels);         double stddevB= stddev(blackPixels);         double varB= var(blackPixels);         System.out.println();         mean(blackPixels);         var(blackPixels);         stddev(blackPixels);         System.out.println(rowTotal);         //ID SHAPES HERE         if (maxB==meanB&&rowTotal==maxB)                 System.out.println("The shape is a square.");         else if (maxB==meanB&&rowTotal!=maxB)                 System.out.println("The shape is a rectangle.");         else if (maxB==rowTotal&&stddevB!=varB)                 System.out.println("The shape is a circle.");         else if(.5*maxB<meanB&&rowTotal>maxB)                 System.out.println("The shape is a triangle.");         else if(meanB!=maxB&&(1/3)*maxB==(1/2)*rowTotal)                 System.out.println("The shape is a polygon.");         else                 System.out.println("The shape is unknown.");         }         public static double max(double[]a) {                 double max=Double.NEGATIVE_INFINITY;                 for(int i=0; i<a.length; i++)                         if(a[i]>max) max=a[i];                 System.out.println("max= "+max);                 return max;         }         public static double mean(double []a) {                 double sum=0.0;                 for(int i=0; i<a.length;i++){                         sum=sum+a[i];                 }                 System.out.println("mean= "+sum/a.length);                 return sum/a.length;         }         public static double var(double[]a) {                 double avg=mean(a);                 double sum=0.0;                 for(int i=0; i<a.length;i++)                         sum+=(a[i]-avg)*(a[i]-avg);                 System.out.println("var= "+sum/(a.length-1));                 return sum/(a.length-1);         }         public static double stddev (double[]a){                 System.out.println("stddev= "+ Math.sqrt(var(a)));                 return Math.sqrt(var(a));                         }   private static void recolor(Color[][] c) {         for(int y=0; y < c.length; y++)             for(int x=0; x < c[y].length; x++)                 if (c[y][x].getRed() < 50)                       c[y][x] = Color.BLACK;                 else c[y][x] = Color.white;         ImageViewer.createImage(c);   } }```
p.s. algoritharium is a .jar file

can anyone point me in the right direction to identify when an image has two shapes in it? thank you!
• 06-19-2011, 11:19 PM
Norm
Is the code you posted supposed to compile?
I get many compiler errors that look like they are caused by mismatched {}s
• 06-19-2011, 11:30 PM
acole5
That's weird, it compiles without any errors on my computer and it doesn't look like I copy and pasted it wrong.
• 06-19-2011, 11:39 PM
Norm
Ok, got a better version that time. But do have compile problems without the algoritharium package.
• 06-19-2011, 11:51 PM
acole5
ooh yeah, if you want to download the file you can here: algoritharium.jar for a PC or here for a Mac algorithariumMac.jar
• 06-19-2011, 11:55 PM
Norm
Thanks.
Have you documented some where how your code works, what it does and how?
What it the algorithm that you are using to find shapes?
• 06-20-2011, 07:51 PM
acole5
Essentially this is how the program is working:
1. Run the program provided previously that recolors the image.
2. Open each of the shape files just to look at them and pick the single shape images square, rectangle and circle to start.
3. Your challenge is to iterate over the color array looking for a black pixel in a row, then to count the consecutive black pixels and store that number in a one dimensional array. Continue this process until that array has the length of each row in the shape. We have had to iterate over an array just to get one piece of information before beginning the process of storing the values found. You will have to determine how many rows there are in order to create the array or use a new data structure available in the Java API that automatically grows.
4. Use your book to help with the data analysis. Page 237 has a nice set of algorithms for analyzing data stored in a one dimensional array. These methods return max, mean, variance, and standard deviation.
5. Print the return value from each of these methods and compare the results between the three different shapes. Also print the width and height of the shape (the width is the max and the height is the length of the array.
6. Analyze the results to come up with a test to distinquish between the three shapes. Run your program on each of the three shapes and have it print unknown or one of those three shapes if it can identify them.

So first I use for loops to find out how big the array should be, then I fill the array with the length of the rows. Then I have if statements identifying the shapes based on the heigh, width, mean, max, variance, and standard deviation. I just need to add something that figures out that there are two shapes and stores the second shape information into a different array.
• 06-20-2011, 08:02 PM
Norm
Quote:

Use your book to help with the data analysis. Page 237 has a nice set of algorithms for analyzing data stored in a one dimensional array. These methods return max, mean, variance, and standard deviation.
Not much use. I don't have the book.

My approach would be to consider the images as a piece of paper with the two shapes on it. Draw a rectangle around each shape and use your algorithm on each rectangle to determine what shape is in it.
Your current algorithm goes from 0,0 to image width/height. Parameterize that code to use the x,y,width,height of a rectangle.
• 06-20-2011, 08:09 PM
acole5
I'm just having problems figuring out if there are one or two shapes in the image. I e-mailed my teacher for help and all he said is: try rotating the image. Do you know how this would help? How would I know which images to rotate?
• 06-20-2011, 08:14 PM
Norm
Did you understand you idea about putting rectangles around each image? You code should be easy to modify to test within a rectangle. A quick test would be to change the code and use 1,1, width-2 height-2 since all the images have a wide border.

The next step would be to find bounding rectangles for the shapes in the image. If there are only 2 images, either draw a line across the image horizontally or vertically to create two rectangles each containing one shape. Finding where to draw the line would be looking for white pixels all across the image after having passed over an image