Пример #1
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;
}
Пример #2
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;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
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;
        }
    }
}
Пример #8
0
bool Robots::sanityChecks(int index) {
    Blob candidate = blobs->get(index);
    //thresholds for smallest allowable blob
    const int blobHeightMin = 3;
    const int blobAreaMin = 15;

    int height = candidate.height();
    int bottom = candidate.getBottom();
    if (candidate.getRight() > 0) {

        //blobs must be large enough
        if (candidate.height()*candidate.width() < blobAreaMin) {
            if (debugRobots){
                cout << "Blob area was too small" << endl;
            }
            return false;
        }

        // uniforms should be wider than they are tall
        if (candidate.height() > candidate.width()) {
            if (debugRobots){
                cout << "Blob was taller than it was wide" << endl;
            }
            return false;
        }

        //a robot cannot be inside another robot
        for (int i = 0; i < blobs->number(); i++) {
            if (i == index) continue;
            if (blobs->blobsOverlap(index, i)) {
                blobs->mergeBlobs(index, i);
                if (debugRobots){
                    cout << "Blob was inside other robot" << endl;
                }
                return false;
            }
        }

        // there ought to be some white below the uniform
        if (bottom < IMAGE_HEIGHT - 10 &&
            !checkWhiteAllignment(candidate)) {
            if (debugRobots) {
                cout << "Bad robot from white alignment check" << endl;
            }
            return false;
        }
        // the last check was pretty general, let's improve
        if (candidate.getBottom() < IMAGE_HEIGHT - candidate.height() * 2
            && !whiteBelow(candidate)) {
            if (debugRobots) {
                cout << "Got rid for lack of white below" << endl;
            }
            return false;
        }
        if (candidate.getTop() > candidate.height() * 2
            && !whiteAbove(candidate)) {
            if (debugRobots) {
                cout << "Got rid for lack of white above" << endl;
            }
            return false;
        }
        // for some blobs we check even harder for white
        if (height < 2 * blobHeightMin && noWhite(candidate)) {
            if (debugRobots) {
                cout << "Got rid of small one for white" << endl;
            }
            return false;
        }

        if (color == NAVY_BIT && vision->pose->getHorizonY(0) < 0 &&
            notGreen(candidate)) {
            if (debugRobots){
                cout << "Got rid for pose check" << endl;
            }
            return false;
        }
        return true;
    }
    return false;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #11
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);
}