Example #1
0
/*  When we're looking for balls it is helpful if they are surrounded by green.
 * The best place to look is underneath.  So let's do that.
 * @param b    the potential ball
 * @return     did we find some green?
 */
bool Ball::greenCheck(Blob b)
{
    const int ERROR_TOLERANCE = 5;
	const int EXTRA_LINES = 10;
	const int MAX_BAD_PIXELS = 4;

    if (b.getRightBottomY() >= IMAGE_HEIGHT - 1 ||
		b.getLeftBottomY() >= IMAGE_HEIGHT-1)
		return true;
    if (b.width() > IMAGE_WIDTH / 2) return true;
    int w = b.width();
    int y = 0;
    int x = b.getLeftBottomX();
	stop scan;
    for (int i = 0; i < w; i+= 2) {
        y = b.getLeftBottomY();
        vertScan(x + i, y, 1, ERROR_TOLERANCE, GREEN, GREEN, scan);
        if (scan.good > 1)
            return true;
    }
    // try one more in case its a white line
    int bad = 0;
    for (int i = 0; i < EXTRA_LINES && bad < MAX_BAD_PIXELS; i++) {
        int pix = thresh->thresholded[min(IMAGE_HEIGHT - 1,
										  b.getLeftBottomY() + i)][x];
        if (pix == GREEN) return true;
        if (pix != WHITE) bad++;
    }
    return false;
}
Example #2
0
/*	Draws the outline of a blob in the specified color.
 * @param b	   the blob
 * @param c	   the color to paint
 */
void Ball::drawBlob(Blob b, int c) {
#ifdef OFFLINE
	thresh->drawLine(b.getLeftTopX(), b.getLeftTopY(),
					 b.getRightTopX(), b.getRightTopY(),
					 c);
	thresh->drawLine(b.getLeftTopX(), b.getLeftTopY(),
					 b.getLeftBottomX(), b.getLeftBottomY(),
					 c);
	thresh->drawLine(b.getLeftBottomX(), b.getLeftBottomY(),
					 b.getRightBottomX(), b.getRightBottomY(),
					 c);
    thresh->drawLine(b.getRightTopX(), b.getRightTopY(),
					 b.getRightBottomX(), b.getRightBottomY(),
					 c);
#endif
}
Example #3
0
/* Print debugging information for a blob.
 * @param b    the blob
 */
void Robots::printBlob(Blob b) {
#if defined OFFLINE
    cout << "Outputting blob" << endl;
    cout << b.getLeftTopX() << " " << b.getLeftTopY() << " " << b.getRightTopX() << " "
            << b.getRightTopY() << endl;
    cout << b.getLeftBottomX() << " " << b.getLeftBottomY() << " " << b.getRightBottomX()
            << " " << b.getRightBottomY() << endl;
#endif
}
Example #4
0
/**
 * Update the robot values from the blob
 *
 * @param b The blob to update our object from.
 */
void VisualRobot::updateRobot(Blob b)
{
    setLeftTopX(b.getLeftTopX());
    setLeftTopY(b.getLeftTopY());
    setLeftBottomX(b.getLeftBottomX());
    setLeftBottomY(b.getLeftBottomY());
    setRightTopX(b.getRightTopX());
    setRightTopY(b.getRightTopY());
    setRightBottomX(b.getRightBottomX());
    setRightBottomY(b.getRightBottomY());
    setX(b.getLeftTopX());
    setY(b.getLeftTopY());
    setWidth(dist(b.getRightTopX(), b.getRightTopY(), b.getLeftTopX(),
                       b.getLeftTopY()));
    setHeight(dist(b.getLeftTopX(), b.getLeftTopY(), b.getLeftBottomX(),
                        b.getLeftBottomY()));
    setCenterX(getLeftTopX() + ROUND2(getWidth() / 2));
    setCenterY(getRightTopY() + ROUND2(getHeight() / 2));
    setDistance(1);
}
Example #5
0
/*  When we're looking for balls it is helpful if they are surrounded by green.
 * The best place to look is underneath, but that doesn't always work.  So let's
 * try the other sides.
 * @param b    the potential ball
 * @return     did we find some green?
 */
bool Ball::greenSide(Blob b)
{
    const int ERROR_TOLERANCE = 5;
	const int X_EXTRA = 8;

    int x = b.getRightBottomX();
    int y = b.getRightBottomY();
	stop scan;
    for (int i = y; i > (b.height()) / 2; i = i - 2) {
        horizontalScan(x, i, 1, ERROR_TOLERANCE, GREEN, GREEN, x - 1,
					   x + X_EXTRA, scan);
        if (scan.good > 0)
            return true;
    }
    x = b.getLeftBottomX();
    y = b.getLeftBottomY();
    for (int i = y; i > (b.height()) / 2; i = i - 2) {
        horizontalScan(x, i, -1, ERROR_TOLERANCE, GREEN, GREEN,
					   x - X_EXTRA, x + 1, scan);
        if  (scan.good == 0)
            return true;
    }
    return false;
}
Example #6
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;
}
Example #7
0
/*  Is the ball at the boundary of the screen?
 * @param b    the ball
 * @return     whether or not it borders a boundary
 */
bool Ball::atBoundary(Blob b) {
    return b.getLeftTopX() == 0 || b.getRightTopX() >= IMAGE_WIDTH -1 ||
		b.getLeftTopY() == 0
        || b.getLeftBottomY() >= IMAGE_HEIGHT - 1;
}
Example #8
0
int  Ball::roundness(Blob b)
{
    const int IMAGE_EDGE = 3;
	const int BIG_ENOUGH = 4;
	const int TOO_BIG_TO_CHECK = 20;
	const int WIDTH_AT_SCREEN_BOTTOM = 15;
	const float RATIO_TO_INT = 10.0f;
	const float CORNER_CHUNK_DIV = 6.0f;

    int w = b.width();
    int h = b.height();
    int x = b.getLeftTopX();
    int y = b.getLeftTopY();
    float ratio = static_cast<float>(w) / static_cast<float>(h);
    int r = 10;

    if ((h < SMALLBALLDIM && w < SMALLBALLDIM && ratio > BALLTOOTHIN &&
		 ratio < BALLTOOFAT)) {
    } else if (ratio > THINBALL && ratio < FATBALL) {
    } else if (y + h > IMAGE_HEIGHT - IMAGE_EDGE || x == 0 || (x + w) >
			   IMAGE_WIDTH - 2 || y == 0) {
        if (BALLDEBUG)
            cout << "Checking ratio on occluded ball:  " << ratio << endl;
        // we're on an edge so allow for streching
        if (h > BIG_ENOUGH && w > BIG_ENOUGH && (y + h > IMAGE_HEIGHT - 2 ||
												 y == 0) &&
			ratio < MIDFAT && ratio > 1) {
            // then sides
        } else if (h > BIG_ENOUGH && w > BIG_ENOUGH
				   && (x == 0 || x + w > IMAGE_WIDTH - 2)
				   && ratio > MIDTHIN && ratio < 1) {
        } else if ((h > TOO_BIG_TO_CHECK || w > TOO_BIG_TO_CHECK)
				   && (ratio > OCCLUDEDTHIN && ratio < OCCLUDEDFAT) ) {
            // when we have big slivers then allow for extra
        } else if (b.getLeftBottomY() > IMAGE_HEIGHT - IMAGE_EDGE &&
				   w > WIDTH_AT_SCREEN_BOTTOM) {
            // the bottom is a really special case
        } else {
            if (BALLDEBUG)
                //cout << "Screening for ratios" << endl;
                return BAD_VALUE;
        }
    } else {
        if (BALLDEBUG) {
            drawBlob(b, BLACK);
            printBlob(b);
            cout << "Screening for ratios " << ratio << endl;
        }
        return BAD_VALUE;
    }
    if (ratio < 1.0) {
        int offRat = ROUND2((1.0f - ratio) * RATIO_TO_INT);
        r -= offRat;
    } else {
        int offRat = ROUND2((1.0f - 1.0f/ratio) * RATIO_TO_INT);
        r -= offRat;
    }
    if (w * h > SMALLBALL) {
        // now make some scans through the blob - horizontal, vertical, diagonal
        int pix;
        int goodPix = 0, badPix = 0;
        if (y + h > IMAGE_HEIGHT - IMAGE_EDGE || x == 0 || (x + w) >
			IMAGE_WIDTH - 2 || y == 0) {
        } else {
            // we're in the screen
            int d = ROUND2(static_cast<float>(std::max(w, h)) /
						   CORNER_CHUNK_DIV);
            int d3 = min(w, h);
            for (int i = 0; i < d3; i++) {
                pix = thresh->thresholded[y+i][x+i];
                if (i < d || (i > d3 - d)) {
                    if (pix == ORANGE || pix == ORANGERED) {
						//drawPoint(x+i, y+i, BLACK);
                        badPix++;
					}
                    else
                        goodPix++;
                } else {
					if (pix == ORANGE || pix == ORANGERED || pix == ORANGEYELLOW)
						goodPix++;
					else if (pix != GREY) {
						badPix++;
						//drawPoint(x+i, y+i, PINK);
					}
				}
                pix = thresh->thresholded[y+i][x+w-i];
                if (i < d || (i > d3 - d)) {
                    if (pix == ORANGE || pix == ORANGERED) {
						//drawPoint(x+w-i, y+i, BLACK);
                        badPix++;
					}
                    else
                        goodPix++;
                } else if (pix == ORANGE || pix == ORANGERED ||
						   pix == ORANGEYELLOW)
                    goodPix++;
                else if (pix != GREY) {
                    badPix++;
					//drawPoint(x+w-i, y+i, BLACK);
				}
            }
			//cout << "here" << endl;
            for (int i = 0; i < h; i++) {
                pix = thresh->thresholded[y+i][x + w/2];
				//drawPoint(x + w/2, y+i, BLACK);
                if (pix == ORANGE || pix == ORANGERED || pix == ORANGEYELLOW) {
                    goodPix++;
                } else if (pix != GREY)
                    badPix++;
            }
        }
        for (int i = 0; i < w; i++) {
            pix = thresh->thresholded[y+h/2][x + i];
			//drawPoint(x+i, y+h/2, BLACK);
            if (pix == ORANGE || pix == ORANGERED || pix == ORANGEYELLOW) {
                goodPix++;
            } else if (pix != GREY)
                badPix++;
        }
        if (BALLDEBUG)
            cout << "Roundness: Good " << goodPix << " " << badPix << endl;
		// if more than 20% or so of our pixels tested are bad, then we toss it out
        if (goodPix < badPix * 5) {
            if (BALLDEBUG)
                cout << "Screening for bad roundness" << endl;
            return BAD_VALUE;
        }
    }
    return 0;
}