Locating multiple blobs in an image

186 views Asked by At

For a computer science class, I'm supposed to write a program that will find the position and the size of an unknown number of aliens in a picture like this one: http://www-bcf.usc.edu/~stejada/csci101/Pix/MARS2.jpg. I currently have the following code:

#include "Myro.h"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "alien.h"
#include <vector>

using std::cout;
using std::cin;
using std::endl;
using std::vector;

void trackBlob(PicturePtr &aPic, int x, int y);
int BlobSize(PicturePtr &aPic, int x, int y, vector<int>& xLocs, vector<int>& yLocs);

vector<alien> found;
int returned;

int main()
{
returned = 0;
cout << "Pick a picture to search 0-5, or choose 6 to quit" << endl;
int selection;
cin >> selection;
PicturePtr thePic;

// Choose a picture to search
bool selecting = true;
while (selecting) {
    switch (selection) {
        case 0:
            thePic = makePicture("MARS.jpg");
            selecting = false;
            break;
        case 1:
            thePic = makePicture("MARS1.jpg");
            selecting = false;
            break;
        case 2:
            thePic = makePicture("MARS2.jpg");
            selecting = false;
            break;
        case 3:
            thePic = makePicture("MARS3.jpg");
            selecting = false;
            break;
        case 4:
            thePic = makePicture("MARS4.jpg");
            selecting = false;
            break;
        case 5:
            thePic = makePicture("MARS6.jpg");
            selecting = false;
            break;
        case 6:
            cout << "Terminating." << endl;
            return 0;
        default:
            cout << "Invalid input. Please try again." << endl << endl;
            break;
    }// end switch
} // end while

// Find the aliens
cout << endl;
cout << "Pic size: " << getHeight(thePic) * getWidth(thePic) << endl << endl;
int numGreen = 0;
for (int i = 0; i < getWidth(thePic); i++) {
    for (int j = 0; j < getHeight(thePic); j++) {
        Pixel pix;
        pix = getPixel(thePic,i,j);

        // Check for alien color
        if (pix.R >= 100 && pix.R <= 120 && pix.G >= 240 && pix.G <= 255 && pix.B >= 1 && pix.B <= 15) {
            trackBlob(thePic,i,j);
            numGreen++;
        }
        else if (pix.R >= 165 && pix.R <= 185 && pix.G >= 215 && pix.G <= 235 && pix.B >= 65 && pix.B <= 85) {
            trackBlob(thePic,i,j);
            numGreen++;
        }
        else if (pix.R >= 130 && pix.R <= 155 && pix.G >= 210 && pix.G <= 230 && pix.B >= 145 && pix.B <= 175) {
            trackBlob(thePic,i,j);
            numGreen;
        }
        else if (pix.R >= 27 && pix.R <= 47 && pix.G <= 265 && pix.G >= 245 && pix.B >= 1 && pix.B <= 10) {
            trackBlob(thePic,i,j);
            numGreen++;
        }
        else if (pix.R >= 240 && pix.R <= 255 && pix.G <= 240 && pix.G >= 255 && pix.B >= 25 && pix.B <= 45) {
            trackBlob(thePic,i,j);
            numGreen++;
        }
        else if (pix.R >= 235 && pix.R <= 255 && pix.G <= 245 && pix.G >= 210 && pix.B >= 200 && pix.B <= 230) {
            trackBlob(thePic,i,j);
            numGreen++;
        }
        else if (pix.R <= 240 && pix.R >= 210 && pix.G <=255 && pix.G >= 240 && pix.B >= 1 && pix.B <= 10) {
            trackBlob(thePic,i,j);
            numGreen++;
        }
    }
}
cout << endl << endl;
cout << "Number of Aliens: " << found.size() << endl;
for (int n = 0; n < found.size(); n++) {
    cout << "Position of Alien #" << n << ": (" << found[n].x << "," << found[n].y << ")" << endl;
    cout << "Size of Alien #" << n << ": " << found[n].size << endl;
}

cout << endl << endl << "Number pixels tried: " << numGreen << endl << endl;
cout << "Times blob returned: " << returned << endl;
show(thePic);
return 0;
}

void trackBlob(PicturePtr &aPic, int x, int y) {
// Just to be safe
Pixel aPixel = getPixel(aPic,x,y);
//if (aPixel.R == 0 && aPixel.G == 0 && aPixel.B == 0)
    //return;

// Find the size of the alien
vector<int> xLocs;
vector<int> yLocs;
int size = BlobSize(aPic,x,y,xLocs,yLocs);
cout << "Blob size: " << size << endl;
returned++;

// Make sure it's big enough to be an alien
if (size < 5) {
    return;
}

alien newAlien;

// Find the position
newAlien.x = 0;
for (int i = 0; i < xLocs.size(); i++) {
    newAlien.x += xLocs[i];
}
newAlien.x = newAlien.x/xLocs.size();

newAlien.y = 0;
for (int j = 0; j < yLocs.size(); j++) {
    newAlien.y += yLocs[j];
}
newAlien.y = newAlien.y/yLocs.size();

found.push_back(newAlien);
}

int BlobSize(PicturePtr &aPic, int x, int y, vector<int>& xLocs, vector<int>& yLocs)
{
if (x >= getWidth(aPic) || x < 0)
    return 0;

Pixel pix = getPixel(aPic,x,y);

// Just to be safe
//if (pix.R == 0 && pix.G == 0 && pix.B == 0)
    //return 0;

bool isAlien = false;
if (pix.R >= 100 && pix.R <= 120 && pix.G >= 240 && pix.G <= 255 && pix.B >= 1 && pix.B <= 15)
    isAlien = true;
else if (pix.R >= 165 && pix.R <= 185 && pix.G >= 215 && pix.G <= 235 && pix.B >= 65 && pix.B <= 85)
    isAlien = true;
else if (pix.R >= 130 && pix.R <= 155 && pix.G >= 210 && pix.G <= 230 && pix.B >= 145 && pix.B <= 175)
    isAlien = true;
else if (pix.R >= 27 && pix.R <= 47 && pix.G <= 265 && pix.G >= 245 && pix.B >= 1 && pix.B <= 10)
    isAlien = true;
else if (pix.R >= 240 && pix.R <= 255 && pix.G <= 240 && pix.G >= 255 && pix.B >= 25 && pix.B <= 45)
    isAlien = true;
else if (pix.R >= 235 && pix.R <= 255 && pix.G <= 245 && pix.G >= 210 && pix.B >= 200 && pix.B <= 230)
    isAlien = true;
else if (pix.R <= 240 && pix.R >= 210 && pix.G <=255 && pix.G >= 240 && pix.B >= 1 && pix.B <= 10)
    isAlien = true;

if (!isAlien)
    return 0;

// Store the location in the position vectors
xLocs.push_back(x);
yLocs.push_back(y);

// Make sure the pixel doesn't get counted again
setPixelColor(aPic,x,y,0,0,0);

int size = 0;

for (int i = 0; i <= 2; i++) {
    for (int j = 0; j <= 2; j++) {
        if (i == 0 && j == 0) {
            break;
        }
        size += BlobSize(aPic,x + (i-1), y + (j-1),xLocs,yLocs);
    }
}

return 1 + size;
}

When I run the code, it says it's found several hundred "aliens." Each one it finds is bigger than the last if that's helpful. I've been staring at this for days and have no idea what's going wrong. Any help would be much appreciated.

Thanks!

1

There are 1 answers

1
Student_in_CSCI101L On

First off, you should remove the comments from BlobSize() like so:

// So pixels aren't counted twice
if (pix.R == 0 && pix.G == 0 && pix.B == 0)
    return 0;

Since BlobSize() changes the counted pixels to black, you need to keep those lines in your code so it doesn't count pixels twice.

Also, your for loop at the end of BlobSize() is slightly wrong. It should look like this:

for (int i = -1; i <= 1; i++) {
    for (int j = -1; j <= 1; j++) {
        // skip pixel at this location
        if (i == 0 && j == 0) {
            continue;
        }
        size += BlobSize(aPic,x + (i-1), y + (j-1),xLocs,yLocs);
    }
}

The way that it was before would check the pixel one above and left of the pixel at the current location, see that i == 0 && j == 0, then skip checking the first column. The program would run BlobSize() on the other 6 pixels (including the one at the current location).

By the way, nice use of vectors and recursion. Sorry if I answered too late and you already turned it in. I'm turning mine in on Sunday because of the extension.