Ejemplo n.º 1
0
void Cross::checkForCrosses() {
    // TODO:  These were thrown together in an hour.  They should
    // be more rigorously determined
    const int maxWidth = 75;
    const int maxHeight = 75;
    const int minWidth = 5;
    const int minHeight = 5;
    const int maxRatio = 5;

    // loop through all the blobs and test the ones that are the right
    // basic size
    for (int i = 0; i < blobs->number(); i++) {
        Blob candidate = blobs->get(i);
        if (CROSSDEBUG) {
            cout << "Blob " << candidate.width() << " " << candidate.height() <<
				endl;
            cout << "Coords " << candidate.getLeft() << " " <<
				candidate.getTop() << endl;
            vision->drawRect(candidate.getLeft(), candidate.getTop(),
                             candidate.width(), candidate.height(), BLACK);
        }
        if (candidate.width() < maxWidth && candidate.height() < maxHeight &&
                candidate.width() > minWidth && candidate.height() > minHeight &&
                candidate.width() < maxRatio * candidate.height()  &&
                candidate.height() < maxRatio * candidate.width()) {
            checkForX(candidate);
        }
    }
}
Ejemplo n.º 2
0
/* Checks out how much of the blob is of the right color.
 * If it is enough returns true, if not false.
 * @param tempobj     the cross we're checking
 * @param minpercent  how good it needs to be
 * @return            was it good enough?
 */
bool Cross::rightBlobColor(Blob tempobj, float minpercent) {
    int x = tempobj.getLeft();
    int y = tempobj.getTop();
    int spanX = tempobj.width();
    int spanY = tempobj.height();
    if (spanX < 1 || spanY < 1) return false;
    int ny, nx, starty, startx;
    int good = 0, total = 0;
    for (int i = 0; i < spanY; i++) {
        starty = y + i;
        startx = x;
        for (int j = 0; j < spanX; j++) {
            nx = startx + j;
            ny = starty;
            if (ny > -1 && nx > -1 && ny < IMAGE_HEIGHT && nx < IMAGE_WIDTH) {
                total++;
                if (thresh->thresholded[ny][nx] == WHITE) {
                    good++;
                }
            }
        }
    }
    float percent = (float)good / (float) (total);
    if (percent > minpercent) {
        return true;
    }
    return false;
}
Ejemplo n.º 3
0
/* Are two blobs close enough that they might actually be the same?
   Note: if the area between is bigger than one of the blobs then can it?
 */
bool Robots::closeEnough(int i, int j) {
    Blob a = blobs->get(i);
    Blob b = blobs->get(j);
    int width1 = a.width();
    int width2 = b.width();
    int height1 = a.height();
    int height2 = b.height();
    int bigWidth = max(width1, width2);
    int bigHeight = max(height1, height2);
    int dist1 = distance(a.getLeft(), a.getRight(), b.getLeft(), b.getRight());
    int dist2 = distance(a.getTop(), a.getBottom(), b.getTop(), b.getBottom());
    if (a.getRight() <= 0 || b.getRight() <= 0) {
        return false;
    }
    if (dist1 > 5 && dist2 > 5) {
        return false;
    }
    if (dist1 < bigHeight && dist2 < bigWidth) {
        return true;
    }
    return false;
}
Ejemplo n.º 4
0
//attempts to find robots where no uniform is visible
//NOTE: currently dangerous in that it gives false positives. needs substantial work
void Robots::findRobotParts(){
    //merge overlapping white blobs into a single blob
    for (int i = 0; i < whiteBlobs->number(); i++){
        for (int j = 0; j < whiteBlobs->number(); j++){
            if (i == j) continue;
            if (whiteBlobs->blobsOverlap(i, j)){
                whiteBlobs->mergeBlobs(i, j);
            }
        }
    }
    //sort the white blobs in descending order by size
    whiteBlobs->sort();

    for (int i = 0; i < whiteBlobs->number(); i++){
        bool aligned = false;
        bool side = false;

        //true if the blob is at the edge of the screen. For now we are only looking
        //at these blobs, since looking at all blobs leads to too many false positives
        if (whiteBlobs->get(i).getLeft() <= 10 ||
            whiteBlobs->get(i).getRight() >= IMAGE_WIDTH-10 ||
            whiteBlobs->get(i).getTop() <= 10 ||
            whiteBlobs->get(i).getBottom() >= IMAGE_HEIGHT-10) {
            side = true;
        }
        if (side){
            //checks if the white blob is aligned with a robot of known team.
            //if it is, we have already indentified this blob
            for (int j = 0; j < blobs->number(); j++){
                if (whiteBlobs->get(i).isAligned(blobs->get(j))) {
                    aligned = true;
                    break;
                }
            }
        }

        //true if we have found a potential robot part
        if (!aligned && side) {
            Blob part = correctBlob(whiteBlobs->get(i));
            //for now just outlines the region we found. Once this method is functional,
            //it should also call updateRobots in some manner
            vision->drawRect(part.getLeft(),
                             part.getTop(),
                             part.width(),
                             part.height(),
                             WHITE);
        }
    }
}
Ejemplo n.º 5
0
/* Given a viable uniform blob, add all vertically
   alligned white blobs to create an "area of interest" for where to more
   rigorously determine where a robot is
   @param robotBlob     potential uniform blob
   @return              blob indicating an area of interest for robot detection
*/
Blob Robots::createAreaOfInterest(Blob robotBlob) {
    int left = robotBlob.getLeft();
    int right = robotBlob.getRight();
    int top = robotBlob.getTop();
    int bottom = robotBlob.getBottom();
    int height = robotBlob.height();
    int width = right-left;

    for (int i = 0; i < whiteBlobs->number(); i++){
        if (whiteBlobs->get(i).isAligned(robotBlob)) {
            robotBlob.merge(whiteBlobs->get(i));
        }
    }

    //places constraints the on the area of interest with knowledge of the relative
    //ratio of the dimensions of the robot to the dimensions of its uniform
    //NOTE: this ratio could be more accurately defined
    if (robotBlob.getLeft() < left-width) robotBlob.setLeft(left-width);
    if (robotBlob.getRight() > right+width) robotBlob.setRight(right+width);
    if (robotBlob.getTop() < top-5*height) robotBlob.setLeft(top-5*height);
    if (robotBlob.getBottom() > bottom+6*height) robotBlob.setBottom(bottom+6*height);

    return robotBlob;
}
Ejemplo n.º 6
0
/* When we are looking down, the shadowed carpet often has lots of Navy.
   Make sure we aren't just looking at carpet
 */
bool Robots::notGreen(Blob candidate) {
    int bottom = candidate.getBottom();
    int top = candidate.getTop();
    int left = candidate.getLeft();
    int right = candidate.getRight();
    int area = candidate.width() * candidate.height() / 5;
    int greens = 0;
    for (int i = left; i < right; i++) {
        for (int j = top; j < bottom; j++) {
            if (Utility::isGreen(thresh->getThresholded(j, i))) {
                greens++;
                if (greens > area) {
                    return true;
                }
            }
        }
    }
    return false;
}
Ejemplo n.º 7
0
/* We have a swatch of color.  Let's make sure that there is some white
   around somewhere as befits our robots.
 */
bool Robots::noWhite(Blob b) {
    const int MINWHITE = 5;

    int left = b.getLeft(), right = b.getRight();
    int top = b.getTop(), bottom = b.getBottom();
    int width = b.width();
    int tops, bottoms;
    for (int i = 1; i < b.height(); i++) {
        tops = 0; bottoms = 0;
        for (int x = left; x <= right; x++) {
            if (top - i >= 0 && Utility::isWhite(thresh->getThresholded(top - i,x)))
                tops++;
            if (bottom + i < IMAGE_HEIGHT &&
                Utility::isWhite(thresh->getThresholded(bottom+i,x)))
                bottoms++;
            if (tops > width / 2 || tops == width) return false;
            if (bottoms > width / 2 || tops == width) return false;
        }
    }
    return true;
}
Ejemplo n.º 8
0
/* Since the white blob check catches a lot of extra stuff like lines,
   we need to check a bit more carefully.
 */
bool Robots::whiteAbove(Blob candidate) {
    int top = candidate.getTop();
    int height = candidate.height();
    int scanline = top - height;
    for (int y = scanline; y > 0 && y > scanline - height; y -= 3) {
        int white = 0;
        int green = 0;
        for (int x = candidate.getLeft(); x < candidate.getRight(); x++) {
            if (Utility::isWhite(thresh->getThresholded(y, x))) {
                white++;
            } else if (Utility::isGreen(thresh->getThresholded(y, x))) {
                green++;
            }
        }
        if (green > candidate.width() / 2 && white == 0) {
            return false;
        }
        if (white > candidate.width() / 4) {
            return true;
        }
    }
    return false;
}
Ejemplo n.º 9
0
/* Since the white blob check catches a lot of extra stuff like lines,
   we need to check a bit more carefully.
 */
bool Robots::whiteBelow(Blob candidate) {
    int bottom = candidate.getBottom();
    int height = candidate.height();
    int scanline = bottom + height;
    for (int y = scanline; y < IMAGE_HEIGHT && y < scanline + height; y += 3) {
        int white = 0;
        int green = 0;
        for (int x = candidate.getLeft(); x < candidate.getRight(); x++) {
            if (Utility::isWhite(thresh->getThresholded(y, x))) {
                white++;
            } else if (Utility::isGreen(thresh->getThresholded(y, x))) {
                green++;
            }
        }
        if (green > candidate.width() / 2 && white == 0) {
            return false;
        }
        if (white > candidate.width() / 4) {
            return true;
        }
    }
    return false;
}
Ejemplo n.º 10
0
void Cross::createObject() {
	// TODO:  These were thrown together in an hour.  They should
	// be more rigorously determined
	const int maxWidth = 75;
	const int maxHeight = 75;
	const int minWidth = 5;
	const int minHeight = 5;
	const int maxRatio = 5;

	// do basic run-length encoding
	if (numberOfRuns > 1) {
		for (int i = 0; i < numberOfRuns; i++) {
			// search for contiguous blocks
			int nextX = runs[i].x;
			int nextY = runs[i].y;
			int nextH = runs[i].h;
			blobs->blobIt(nextX, nextY, nextH);
		}
	}
	if (CROSSDEBUG)
		cout << blobs->number() << " white blobs" << endl;
	// loop through all the blobs and test the ones that are the right
	// basic size
	for (int i = 0; i < blobs->number(); i++) {
		Blob candidate = blobs->get(i);
		if (CROSSDEBUG) {
			cout << "Blob " << candidate.width() << " " << candidate.height() << endl;
			cout << "Coords " << candidate.getLeft() << " " << candidate.getTop() << endl;
		}
		if (candidate.width() < maxWidth && candidate.height() < maxHeight &&
			candidate.width() > minWidth && candidate.height() > minHeight &&
			candidate.width() < maxRatio * candidate.height()  &&
			candidate.height() < maxRatio * candidate.width()) {
			checkForX(candidate);
		}
	}
}
Ejemplo n.º 11
0
/* We have two blobs that are reasonably close.  See if they should be
   merged.
*/
void Robots::checkMerge(int i, int j) {
    Blob a = blobs->get(i);
    Blob b = blobs->get(j);
    if (debugRobots) {
        cout << endl << endl << "Checking merge" << endl;
        printBlob(a);
        printBlob(b);
    }
    int dist1 = distance(a.getLeft(), a.getRight(), b.getLeft(), b.getRight());
    int dist2 = distance(a.getTop(), a.getBottom(), b.getTop(), b.getBottom());
    int green = 0;
    int col = 0;
    int miss = 0;
    // top to bottom defines the y region between the two
    int top = max(a.getTop(), b.getTop());
    int bottom = min(a.getBottom(), b.getBottom());
    int midx = (a.getLeft() + a.getRight()) / 2;
    // left to right defines the x region between the two
    int left = a.getRight();
    int right = b.getLeft();
    int midy = (a.getTop() + a.getBottom()) / 2;
    int ii;
    // check if they overlap in either dimension
    if (left > right) {
        // they overlap in x so we'll swap left and right
        int temp = left;
        left = right;
        right = temp;
    }
    if (top > bottom) {
        int temp = top;
        top = bottom;
        bottom = temp;
    }
    int width = right - left + 1;
    int height = bottom - top + 1;
    int area = max(10, width * height / 27);
    int stripe = max(width, height);
    for (int x = left; x < right; x+=3) {
        for (int y = top; y < bottom; y+=3) {
            if (debugRobots) {
                vision->drawPoint(x, y, MAROON);
            }
            if (Utility::colorsEqual(thresh->getThresholded(y, x), color)) {
                col++;
                if (col > area || col > stripe) {
                    blobs->mergeBlobs(i, j);
                    if (debugRobots) {
                        cout << "Merge" << endl;
                    }
                    return;
                }
            } else if (Utility::isGreen(thresh->getThresholded(y, x))) {
                green++;
                if (green > 5) {
                    return;
                }
            } else if (Utility::isWhite(thresh->getThresholded(y, x))) {
                miss++;
                if (miss > area / 9 || miss > stripe) {
                    return;
                }
            }
        }
    }
    if (col > min(width, height) && green < 3) {
        blobs->mergeBlobs(i, j);
        if (debugRobots) {
            cout << "Merge" << endl;
        }
    }
}
Ejemplo n.º 12
0
//correct the area of interest to a reasonable estimate of the robot
Blob Robots::correctBlob(Blob area){

    int left = max(0, area.getLeft());
    int right = min(area.getRight(), IMAGE_WIDTH);
    int top = max(0, area.getTop());
    int bottom = min(area.getBottom(), IMAGE_HEIGHT);
    int width = right - left;
    int height = bottom - top;

    int nonRobot = 0;

    //uncomment for debugging of corrections. Drawn rect is blob before correction
    //vision->drawRect(left,top, width, height, WHITE);

    //correct left side
    for (int x = left; x < left + (width/2); x++) {
        for (int y = top; y < bottom; y++) {
            if (Utility::isGreen(thresh->getThresholded(y,x)) ||
                Utility::isOrange(thresh->getThresholded(y,x))) {
                nonRobot++;
            }
            if (nonRobot > .4*height) {
                area.setLeft(x+1);
                nonRobot = -1;
                break;
            }
        }
        if (nonRobot != -1) break;
        nonRobot = 0;
    }

    //correct right side
    for (int x = right; x > left + (width/2); x--) {
        for (int y = top; y < bottom; y++) {
            if (Utility::isGreen(thresh->getThresholded(y,x)) ||
                Utility::isOrange(thresh->getThresholded(y,x))) {
                nonRobot++;
            }
            if (nonRobot > .4*height) {
                area.setRight(x-1);
                nonRobot = -1;
                break;
            }
        }
        if (nonRobot != -1) break;
        nonRobot = 0;
    }

    //correct top
    for (int y = top; y < top + (height/2); y++) {
        for (int x = left; x < right; x++) {
            if (Utility::isGreen(thresh->getThresholded(y,x)) ||
                Utility::isOrange(thresh->getThresholded(y,x))) {
                nonRobot++;
            };
            if (nonRobot > .4*width) {
                area.setTop(y+1);
                nonRobot = -1;
                break;
            }
        }
        if (nonRobot != -1) break;
        nonRobot = 0;
    }

    //correct bottom
    for (int y = bottom; y > top + (height/2); y--) {
        for (int x = left; x < right; x++) {
            if (Utility::isGreen(thresh->getThresholded(y,x)) ||
                Utility::isOrange(thresh->getThresholded(y,x))) {
                nonRobot++;
            }
            if (nonRobot > .4*width) {
                area.setBottom(y-1);
                nonRobot = -1;
                break;
            }
        }
        if (nonRobot != -1) break;
        nonRobot = 0;
    }

    return area;
}
Ejemplo n.º 13
0
bool Ball::badSurround(Blob b) {
	// basically check around the blob and see if it is ok - ideally we'd have
	// some green, worrisome would be lots of RED
	static const int SURROUND = 12;

	const float GREEN_PERCENT = 0.1f;

	int x = b.getLeftTopX();
	int y = b.getLeftTopY();
	int w = b.width();
	int h = b.height();
	int surround = min(SURROUND, w/2);
	int greens = 0, orange = 0, red = 0, borange = 0, pix, realred = 0,
			yellows = 0;

	// now collect information on the area surrounding the ball and the ball
	x = max(0, x - surround);
	y = max(0, y - surround);
	w = w + surround * 2;
	h = h + surround * 2;
	for (int i = 0; i < w && x + i < IMAGE_WIDTH; i++) {
		for (int j = 0; j < h && y + j < IMAGE_HEIGHT; j++) {
			pix = thresh->getThresholded(y + j,x + i);
			if (pix == ORANGE || pix == ORANGEYELLOW) {
				orange++;
                if (x + i >= b.getLeft() && x + i <= b.getRight() &&
                    y + j >= b.getTop() && y + j <= b.getBottom()) {
                    borange++;
                }
			} else if (pix == RED) {
				realred++;
			} else if (pix == ORANGERED) {
				red++;
			} else if (pix == GREEN) {
				greens++;
			} else if (pix == YELLOW && j < surround) {
				yellows++;
            }
		}
	}
	if (BALLDEBUG) {
		cout << "Surround information " << red << " " << realred << " "
				<< orange << " " << borange << " " << greens << " "
				<< yellows << endl;
	}
	if (realred > borange) {
		if (BALLDEBUG) {
			cout << "Too much real red" << endl;
		}
		return true;
	}
	if (realred > greens && w * h < 2000) {
		if (BALLDEBUG) {
			cout << "Too much real red versus green" << endl;
		}
		return true;
	}
	if (realred > borange && realred > orange) {
		if (BALLDEBUG) {
			cout << "Too much real red vs borange" << endl;
		}
		return true;
	}
	if (orange - borange > borange * 0.3 && orange - borange > 10) {
		if (BALLDEBUG) {
			cout << "Too much orange outside of the ball" << endl;
		}
		// We can run into this problem with reflections - let's see if
		// we're up against a post or something
		if (yellows > w * 3) {
			if (BALLDEBUG) {
				cout << "But lots of yellow, doing nothing " << endl;
			}
			return false;
		} else {
			return true;
		}
	}
	if ((red > orange) &&
			(static_cast<float>(greens) <
					(static_cast<float>(w * h) * GREEN_PERCENT))) {
		if (BALLDEBUG) {
			cout << "Too much real orangered without enough green" << endl;
		}
		return true;
	}
	if (red > orange || (realred > greens && realred > 2 * w &&
            realred > borange * 0.1))  {
		if (BALLDEBUG) {
			cout << "Too much real red - doing more checking" << endl;
		}
		x = b.getLeftTopX();
		y = b.getLeftBottomY();
        if (nearImageEdgeX(x, 2) || nearImageEdgeX(x+b.width(), 2) ||
            nearImageEdgeY(y, 2)) {
			if (BALLDEBUG) {
				cout << "Dangerous corner location detected " << x << " "
                     << y << " " << w << endl;
			}
			return true;
		}
		return roundness(b) == BAD_VALUE;
	}
	return false;
}
Ejemplo n.º 14
0
/* Returns true is the blob abuts any image edge
   @param b      the blob to check
   @return       true when the blob is near an edge
 */
bool Ball::nearEdge(Blob b) {
    return nearImageEdgeX(b.getLeft(), 1) || nearImageEdgeX(b.getRight(), 1) ||
        nearImageEdgeY(b.getTop(), 1) || nearImageEdgeY(b.getBottom(), 2);
}