vector<Plate> DetectRegions::segment(Mat input){ vector<Plate> output; //convert image to gray Mat img_gray; //= *new Mat(input.size().width,input.size().height, CV_8UC1); cvtColor(input, img_gray, CV_BGR2GRAY); blur(img_gray, img_gray, Size(5,5)); //Finde vertical lines. Car plates have high density of vertical lines Mat img_sobel; Sobel(img_gray, img_sobel, CV_8U, 1, 0, 3, 1, 0, BORDER_DEFAULT); if(showSteps) imshow("Sobel", img_sobel); //threshold image Mat img_threshold; threshold(img_sobel, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY); if(showSteps) imshow("Threshold", img_threshold); //Morphplogic operation close Mat element = getStructuringElement(MORPH_RECT, Size(17, 3) ); morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element); if(showSteps) imshow("Close", img_threshold); //Find contours of possibles plates vector< vector< Point> > contours; findContours(img_threshold, contours, // a vector of contours CV_RETR_EXTERNAL, // retrieve the external contours CV_CHAIN_APPROX_NONE); // all pixels of each contours //Start to iterate to each contour founded vector<vector<Point> >::iterator itc= contours.begin(); vector<RotatedRect> rects; //Remove patch that are no inside limits of aspect ratio and area. while (itc!=contours.end()) { //Create bounding rect of object RotatedRect mr= minAreaRect(Mat(*itc)); if( !verifySizes(mr)){ itc= contours.erase(itc); }else{ ++itc; rects.push_back(mr); } } // Draw blue contours on a white image cv::Mat result; input.copyTo(result); cv::drawContours(result,contours, -1, // draw all contours cv::Scalar(255,0,0), // in blue 1); // with a thickness of 1 for(int i=0; i< rects.size(); i++){ //For better rect cropping for each posible box //Make floodfill algorithm because the plate has white background //And then we can retrieve more clearly the contour box circle(result, rects[i].center, 3, Scalar(0,255,0), -1); //get the min size between width and height float minSize=(rects[i].size.width < rects[i].size.height)?rects[i].size.width:rects[i].size.height; minSize=minSize-minSize*0.5; //initialize rand and get 5 points around center for floodfill algorithm srand ( time(NULL) ); //Initialize floodfill parameters and variables Mat mask; mask.create(input.rows + 2, input.cols + 2, CV_8UC1); mask= Scalar::all(0); int loDiff = 30; int upDiff = 30; int connectivity = 4; int newMaskVal = 255; int NumSeeds = 10; Rect ccomp; int flags = connectivity + (newMaskVal << 8 ) + CV_FLOODFILL_FIXED_RANGE + CV_FLOODFILL_MASK_ONLY; for(int j=0; j<NumSeeds; j++){ Point seed; seed.x=rects[i].center.x+rand()%(int)minSize-(minSize/2); seed.y=rects[i].center.y+rand()%(int)minSize-(minSize/2); circle(result, seed, 1, Scalar(0,255,255), -1); int area = floodFill(input, mask, seed, Scalar(255,0,0), &ccomp, Scalar(loDiff, loDiff, loDiff), Scalar(upDiff, upDiff, upDiff), flags); } if(showSteps) imshow("MASK", mask); //cvWaitKey(0); //Check new floodfill mask match for a correct patch. //Get all points detected for get Minimal rotated Rect vector<Point> pointsInterest; Mat_<uchar>::iterator itMask= mask.begin<uchar>(); Mat_<uchar>::iterator end= mask.end<uchar>(); for( ; itMask!=end; ++itMask) if(*itMask==255) pointsInterest.push_back(itMask.pos()); RotatedRect minRect = minAreaRect(pointsInterest); if(verifySizes(minRect)){ // rotated rectangle drawing Point2f rect_points[4]; minRect.points( rect_points ); for( int j = 0; j < 4; j++ ) line( result, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 1, 8 ); //Get rotation matrix float r= (float)minRect.size.width / (float)minRect.size.height; float angle=minRect.angle; if(r<1) angle=90+angle; Mat rotmat= getRotationMatrix2D(minRect.center, angle,1); //Create and rotate image Mat img_rotated; warpAffine(input, img_rotated, rotmat, input.size(), CV_INTER_CUBIC); //Crop image Size rect_size=minRect.size; if(r < 1) swap(rect_size.width, rect_size.height); Mat img_crop; getRectSubPix(img_rotated, rect_size, minRect.center, img_crop); Mat resultResized; resultResized.create(33,144, CV_8UC3); resize(img_crop, resultResized, resultResized.size(), 0, 0, INTER_CUBIC); //Equalize croped image Mat grayResult; cvtColor(resultResized, grayResult, CV_BGR2GRAY); blur(grayResult, grayResult, Size(3,3)); grayResult=histeq(grayResult); if(saveRegions){ stringstream ss(stringstream::in | stringstream::out); ss << "tmp/" << filename << "_" << i << ".jpg"; imwrite(ss.str(), grayResult); } output.push_back(Plate(grayResult,minRect.boundingRect())); } } if(showSteps) imshow("Contours", result); return output; }
void ClothingSearcher::getTheMaskOfCloth(const Mat &image, Mat &mask, const std::vector<int> floodfill_thresholds ) { if( image.channels() == 1 ) return; //get the mask of cloth region using floodfill algorithm Mat edges; computeEdgeMap( image, edges ); //to lower down the complexity, resize the original image to smaller one Mat small_image; Size small_size( image.cols, image.rows ); if( image.cols > 320 ){ float scale = image.cols / 320; small_size.width = image.cols / scale; small_size.height = image.rows / scale; cv::resize( image, small_image, small_size ); } else small_image = image.clone(); //convert to yuv color space Mat yuv = Mat( small_size, CV_8UC3 ); cvtColor( small_image, yuv, CV_BGR2RGB ); //the mask used in floodfill should be 2 pixels widther and higher than the image int sw = small_size.width; int sh = small_size.height; Mat mask_plus_border; mask_plus_border = Mat::zeros( sh + 2, sw + 2, CV_8UC1 ); mask = mask_plus_border( cv::Rect( 1, 1, sw, sh ) ); cv::resize( edges, mask, small_size ); closeOperation( mask ); cv::Rect rect; prepareSeedsRegionForFloodfill( small_image, rect ); rectangle( small_image, rect, Scalar( 0, 255, 0 ) ); //imshow( "tets", small_image ); waitKey(0); Scalar lowerDiff = Scalar( floodfill_thresholds[0], floodfill_thresholds[0], floodfill_thresholds[0] ); Scalar upperDiff = Scalar( floodfill_thresholds[0], floodfill_thresholds[0], floodfill_thresholds[0]); const int CONNECTED_COMPONENTS = 4; const int flags = CONNECTED_COMPONENTS | FLOODFILL_FIXED_RANGE | FLOODFILL_MASK_ONLY; Mat edge_mask = mask.clone(); const int X_POINTS = 8; const int Y_POINTS = 8; const int X_STEP = rect.width / X_POINTS; const int Y_STEP = rect.height / Y_POINTS; for( int i = rect.x + X_STEP; i < (int)(rect.x + rect.width ); i += X_STEP ){ for( int j = rect.y + Y_STEP; j < (int)(rect.y + rect.height ); j += Y_STEP ){ circle( small_image, cv::Point( i, j), 3, Scalar( 0, 0, 255 ) ); floodFill( yuv, mask_plus_border, cv::Point( i, j), Scalar(), NULL, lowerDiff, upperDiff, flags ); } } //imshow( "mask", small_image ); waitKey(0); mask -= edge_mask; }
/******************************************************************************* * Function: extractFGTargets * Description: extract FG targets with given conditions and return objects * Arguments: inImg - input image fgImg - output FG mask image seLength - length of structuring elements (opening) threshVal - threshold value for converting to binary image minArea - minimum area of FG targets maxArea - maximum area of FG targets minAspRatio - minimum aspect ratio of FG targets maxAspRatio - maximum aspect ratio of FG targets * Returns: vector<FGObject>* - all extracted FG targets * Comments: * Revision: *******************************************************************************/ vector<FGObject>* FGExtraction::extractFGTargets(InputArray inImg, OutputArray fgImg, int seLength, int threshVal, double minArea, double maxArea, double minAspRatio, double maxAspRatio) { double theta = 0.4; if(!inImg.obj) return NULL; _inImg = inImg.getMat(); this->init(); //showImage("inImg", _inImg); // background subtraction by opening int err = subtractBGOpenDiagonal(inImg, _bgsImg, threshVal, seLength); if (err>0) { vector<FGObject>* fgObjects = new vector<FGObject>; return fgObjects; } //subtractBGMedian(inImg.getMat(), bgSubImg, threshVal, seLength); //showImage("inImg", _inImg, 0, 1); //showImage("bgSub", _bgsImg); // get the contour vector<vector<Point>> contours = extractContours(_bgsImg); //cout<<contours.size()<<endl; // double local thresholding // histogram backprojection Mat mask = Mat::zeros(_bgsImg.size(), CV_8U); vector<int> areas(contours.size()); int cnt = 0; int argMax = 0; int max_area = 0; for(vector<vector<Point> >::const_iterator it = contours.begin(); it != contours.end(); ++it){ Rect uprightBox = boundingRect(*it); areas[cnt] = uprightBox.height*uprightBox.width; if (areas[cnt]>max_area) { max_area = areas[cnt]; argMax = cnt; } cnt++; } //showImage("inImg", _inImg, 0, 1); vector<Point> largestContour = contours[argMax]; //***** only use the largest contour RotatedRect orientedBox = orientedBoundingBox(largestContour); orientedBox.size.width *= 1.5; orientedBox.size.height *= 1.5; ellipse(mask, orientedBox, Scalar(255), -1); //Rect tempRect = boundingRect(largestContour); //Mat tempImg = mask(tempRect); //imshow("tempImg", tempImg); //imshow("mask", mask); //waitKey(0); // double local thresholding double percentage = 0.8; doubleThresholdByValue(percentage, mask); /*finish = clock(); duration = (double)(finish - start) / (double)CLOCKS_PER_SEC; cout << duration << " sec" << endl; start = clock();*/ // remove noise by a median filter medianBlur(_fgHighImg, _fgHighImg, 3); medianBlur(_fgLowImg, _fgLowImg, 3); //showImage("_fgHighImg", _fgHighImg); //showImage("_fgLowImg", _fgLowImg); /*finish = clock(); duration = (double)(finish - start) / (double)CLOCKS_PER_SEC; cout << duration << " sec" << endl; start = clock();*/ // merge two masks using histogram backprojection //showImage("_fgImg", _fgImg); //showImage("mask", mask); updateByHistBackproject(theta, mask); ellipse(mask, orientedBox, Scalar(0), -1); ellipse(_fgHighImg, orientedBox, Scalar(0), -1); ellipse(_fgLowImg, orientedBox, Scalar(0), -1); //} // thresholding by area and variance #ifdef IMAGE_DOWNSAMPLING int dilateSESize = 3; int erodeSESize = 3; int varThresh = 30; #else int dilateSESize = 7; int erodeSESize = 7; int varThresh = 30; #endif //showImage("fg high", _fgHighImg, 0, 1); //showImage("fg low", _fgLowImg, 0, 1); //showImage("after histbp", _fgImg, 0); thresholdByAreaRatioVar(minArea, maxArea, dilateSESize, erodeSESize, minAspRatio, maxAspRatio, varThresh); //showImage("after area threshold", _fgImg, 0); // post-processing postProcessing(_fgImg, _fgImg); //imshow("_fgImg",_fgImg); //waitKey(0); // fill the holes of the fgImg _fgImg.copyTo(fgImg); floodFill(fgImg, cv::Point(0,0), Scalar(255)); //imshow("fgImg",fgImg); //waitKey(0); bitwise_not(fgImg, fgImg); bitwise_or(fgImg, _fgImg, _fgImg); //imshow("inImg", inImg); //imshow("_fgImg",_fgImg); //waitKey(0); // opening RotatedRect rotatedR = fitEllipse(Mat(largestContour)); float objHeight = min(rotatedR.size.height,rotatedR.size.width); int seSize = int(objHeight/10.0+0.5); Mat se = getStructuringElement(MORPH_ELLIPSE, Size(seSize, seSize)); //***** choose different size according to object height morphologyEx(_fgImg, _fgImg, MORPH_OPEN, se); //imshow("_fgImg",_fgImg); //waitKey(0); // close morphologyEx(_fgImg, _fgImg, MORPH_CLOSE, se); // timer /*clock_t start, finish; double duration = 0.0; start = clock(); finish = clock(); duration = (double)(finish - start) / (double)CLOCKS_PER_SEC; cout << duration << " sec" << endl;*/ thresholdByAreaRatioVar(0.5*minArea, maxArea, 1, 1, minAspRatio, maxAspRatio, 30); // push targets into our vector //Mat largeInImg; #ifdef IMAGE_DOWNSAMPLING resize(_fgImg, _fgImg, Size(), 2, 2, INTER_LINEAR); resize(_inImg, largeInImg, Size(), 2, 2, INTER_LINEAR); #endif //tempImg = _fgImg.clone(); //findContours(tempImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); //tempImg.release(); //imshow("_fgImg",_fgImg); //waitKey(0); contours = extractContours(_fgImg); vector<FGObject>* fgObjects = new vector<FGObject>; //Mat mask8U = Mat::zeros(largeInImg.size(), CV_8U); for (size_t i = 0; i < contours.size(); i++){ double area = contourArea(contours[i]); RotatedRect orientedRect = orientedBoundingBox(contours[i]); Point2f points[4]; orientedRect.points(points); /* orientedRect.size.width *= 1.5; orientedRect.size.height *= 1.5; ellipse(mask8U, orientedRect, Scalar(255), -1); int channels[] = {0}; int nbins = 16; const int histSize[] = {nbins}; float range[] = {0, 255}; const float* ranges[] = {range}; Mat hist; cv::calcHist(&largeInImg, 1, channels, mask8U, hist, 1, histSize, ranges); */ // push targets into our vector FGObject* obj = new FGObject; //obj->histogram = hist; obj->setObjectProperties(area, orientedRect.angle, contours[i], points, SOURCE_UNRECTIFIED); if(obj->isPartialOut(_fgImg.cols, _fgImg.rows) == false){ fgObjects->push_back(*obj); } delete obj; //ellipse(mask8U, orientedRect, Scalar(0), -1); } // eliminate artifacts with width of 1 at the border... rectangle(_fgImg, Point(0,0), Point(_fgImg.cols-1, _fgImg.rows-1), Scalar(0)); fgImg.getMatRef() = _fgImg.clone(); return fgObjects; }
Mat& CHandGestureRecognitionSystemDlg::FeatureDetect(const Mat& image_input, Mat& image_output) { image_input.copyTo(image_output); cvtColor(image_output, image_output, CV_BGR2GRAY); #ifdef _DEBUG TRACE("gray image channels = %d\n", image_output.channels()); #endif // morphology Mat kernel = Mat(3,3,CV_8UC1, Scalar(255)); morphologyEx(image_output, image_output, MORPH_OPEN, kernel); // floodfill int num_floodfill = 0; int area_max = 0; int value_max = 0; for (int i = 0; i < image_output.rows; i++) { unsigned char* p_out = image_output.ptr<uchar>(i); for (int j = 0; j < image_output.cols; j++) { if (*(p_out + j) == 255) { num_floodfill++; Scalar new_val = Scalar(num_floodfill); Point seed = Point(j, i); CRect rect; int area = floodFill(image_output,seed, new_val); if (area > area_max) { area_max = area; value_max = num_floodfill; } } } } // max area int area_left = image_output.cols; int area_right = 0; int area_top = image_output.rows; int area_buttom = 0; for (int i = 0; i < image_output.rows; i++) { unsigned char* p_out = image_output.ptr<uchar>(i); for (int j = 0; j < image_output.cols; j++) { if (*(p_out + j) == value_max) { *(p_out + j) = 255; if (area_left > j) area_left = j; if (area_right < j) area_right = j; if (area_top > i) area_top = i; if (area_buttom < i) area_buttom = i; } else { *(p_out + j) = 0; } } } #ifdef _DEBUG TRACE("area_left = %d\n", area_left); TRACE("area_right = %d\n", area_right); TRACE("area_top = %d\n", area_top); TRACE("area_buttom = %d\n", area_buttom); #endif // rectangle rectangle(image_output, Point(area_left, area_top), Point(area_right, area_buttom), Scalar(255), 5); // moment Moments moment = moments(image_output); int center_x = moment.m10 / moment.m00; int center_y = moment.m01 / moment.m00; point_end = Point(center_x, center_y); circle(image_output, point_end, 10, Scalar(255), 5); GetVector(point_begin, point_end); if (vector_length >= 20 || point_begin == Point(image_width / 2, image_height / 2)) { point_begin = point_end; } #ifdef _DEBUG TRACE("vector_length = %f\n", vector_length); TRACE("vector_angle = %f\n", vector_angle); #endif return image_output; }
void GameEngine::generateLevel() { //Clear out the last level for (vector<Actor*>::iterator it = monsters.begin(); it != monsters.end(); ++it) delete (*it); monsters.clear(); for (vector<Pickup*>::iterator it = pickups.begin(); it != pickups.end(); ++it) delete (*it); pickups.clear(); map.clear(); playableMap.clear(); //Set tile graphics for curr floor if (currLevel == 1) { wallTile = 0x103; floorTile = 0x100; } else if (currLevel > 1) { wallTile = 0x14D; floorTile = 0x13E; delete boss; } //Initialize the outer map vector for (int i = 0; i < worldSize; i++) { vector<Cell> v; map.push_back(v); } //Generate the map boundaries lib.loop_portion(Point(0, 0), Point(worldSize, worldSize), [&](Point p) { Cell c(p, 2, wallTile, 0); map[p.x()].push_back(c); }); //Generate the random rooms for (int i = 0; i < rand() % 130 + 100; i++) { Point pStart((rand() % 55 + 1), (rand() % 55 + 1)); Point pEnd(pStart.x() + (rand() % 6 + 3), pStart.y() + (rand() % 6 + 3)); fillBox(pStart, pEnd); } //Flood fill to connect the world int currZone = 0; vector<int> zoneSize; lib.loop_portion(Point(0, 0), Point(worldSize, worldSize), [&](Point p) { if (map[p.x()][p.y()].getCellType() != 2 && map[p.x()][p.y()].getZone() == 0) { currZone++; int size = floodFill(map[p.x()][p.y()].getLoc(), currZone, 0); zoneSize.push_back(size); } }); //Get biggest zone in array int max = zoneSize[0]; int largestZone = 0; for (unsigned int i = 1; i < zoneSize.size(); i++) { if (zoneSize[i] > max) { largestZone = i; max = zoneSize[i]; } } largestZone++; //Offset for vector index //Get rid of everything but largest zone int end = worldSize - 1; lib.loop_portion(Point(0, 0), Point(worldSize, worldSize), [&](Point p) { Cell& c = map[p.x()][p.y()]; if (c.getZone() != largestZone) { if ((p.x() + 1 < end && map[p.x() + 1][p.y()].getZone() == largestZone) || (p.x() - 1 > 0 && map[p.x() - 1][p.y()].getZone() == largestZone) || (p.y() + 1 < end && map[p.x()][p.y() + 1].getZone() == largestZone) || (p.y() - 1 > 0 && map[p.x()][p.y() - 1].getZone() == largestZone) || (p.x() - 1 > 0 && p.y() - 1 > 0 && map[p.x() - 1][p.y() - 1].getZone() == largestZone) || (p.x() - 1 > 0 && p.y() + 1 < end && map[p.x() - 1][p.y() + 1].getZone() == largestZone) || (p.x() + 1 < end && p.y() - 1 > 0 && map[p.x() + 1][p.y() - 1].getZone() == largestZone) || (p.x() + 1 < end && p.y() + 1 < end && map[p.x() + 1][p.y() + 1].getZone() == largestZone)) { c.setTile(wallTile); c.setTileType(2); } else { c.setTile(0); c.setTileType(2); } } else if (c.getLoc().x() == end) c.setTile(0); }); //Set player starting position lib.loop_portion(Point(0, 0), Point(worldSize - 1, worldSize - 1), [&](Point p) { if (map[p.x()][p.y()].getZone() != 0 && map[p.x()][p.y()].getCellType() != 2) playableMap.push_back(map[p.x()][p.y()].getLoc()); }); //Add monsters for (unsigned int i = 0; i < playableMap.size(); i++) { int chance = rand() % 30; if (chance == 15) { //Make the monster ActorDef def = pickfromtable<ActorDef>(actordefs); monsters.push_back(new Actor(def, playableMap[i], false, false)); map[playableMap[i].x()][playableMap[i].y()].setActor(monsters.back()); //Give chance to spawn with item chance = rand() % 5 + 1; //Give 10% chance to spawn if (chance == 3) { PickupDef def = pickfromtable<PickupDef>(pickupdefs); pickups.push_back(new Pickup(def, playableMap[i])); map[playableMap[i].x()][playableMap[i].y()].setPickup(pickups.back()); } } } //Set starting pos Point heroLoc = getRandomLoc(); screenOrientation = heroLoc; hero->setLoc(screenOrientation); //Add stairs, shop, boss stairLoc = addToRandomLoc(Cell(Point(), 5, 0x1A0, -1)); shop = Shop(addToRandomLoc(Cell(Point(), 6, 0x0C0, -1)), currLevel, pickupdefs, &lib, hero, &log, &invLog); bossLoc = addToRandomLoc(Cell(Point(), 7, 0x1AB, -1)); bossInRoomLoc = Point(5, 2); //Instantiate the boss map for (int i = 0; i < bossMapSize; i++) { vector<Cell> row; for (int j = 0; j < bossMapSize; j++) { if (i == 0 || i == bossMapSize - 1 || j == 0 || j == bossMapSize - 1) row.push_back(Cell(Point(i, j), 2, 0x14B, 1)); else row.push_back(Cell(Point(i, j), 1, 0x122, 1)); } bossMap.push_back(row); } //Add the boss to its location in the boss map int which = rand() % bossdefs.size(); boss = new Actor(bossdefs[which], bossInRoomLoc, false, true); bossMap[bossInRoomLoc.x()][bossInRoomLoc.y()].setActor(boss); }
int main() { int t, row, col, i, j, count = 0; unsigned char **Room; unsigned char temp; FILE *fp; fp = fopen("input.txt", "r"); if (fp == NULL) return 0; /* start FILE IO */ fscanf(fp, "%d", &t); /* read Data Number */ while (t--) { fscanf(fp, "%d %d", &col, &row); /* read Data */ Room = (unsigned char**)malloc(sizeof(unsigned char*)*row); /* read Room data */ for (i = 0; i < row; i++) Room[i] = (unsigned char*)malloc(sizeof(unsigned char)*(col)); for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { fscanf(fp, "%c", &temp); while ((temp != '.') && (temp != '+')) fscanf(fp, "%c", &temp); Room[i][j] = temp; } } for (i = 1; i < row-1; i++) for (j = 0; j < col; j++) if (Room[i][j] == '.') count += floodFill(Room, i, j, '.', '+', &count); /* figure out result */ printf("%d\n", count); /* print output */ Sorting(roomSIZE, 0, count); for (i = 0; i < count; i++) printf("%d ", roomSIZE[i]); printf("\n"); for (i = 0; i < row; i++) /* initialize Room memory */ { free(Room[i]); Room[i] = NULL; } free(Room); Room = NULL; for (i = 0; i < count; i++) roomSIZE[i] = 0; /* initialize roomsize */ count = 0; /* initialize room counter */ } fclose(fp); /* close FILE IO */ return 1; }
void colorFill( int x, int y, COLOR fillColor ) { //boundaryFill(x, y, fillColor); floodFill(x, y, fillColor); }
static void gpath_draw_filled_custom(GContext* ctx, GPath *path, GColor8 fill_color){ if(path->num_points == 0) return; GPoint offset = path->offset; int32_t rotation = path->rotation; int32_t s = sin_lookup(rotation); int32_t c = cos_lookup(rotation); // Rotate each point of the gpath and memorize the min/max GPoint* points_rot = malloc(sizeof(GPoint) * path->num_points); GPoint top_right = (GPoint){(1 << 15)-1,(1 << 15)-1}; GPoint bottom_left= (GPoint){-(1 << 15),-(1 << 15)}; for(uint32_t i=0; i<path->num_points; i++){ points_rot[i].x = (path->points[i].x * c - path->points[i].y * s) / TRIG_MAX_RATIO + offset.x; points_rot[i].y = (path->points[i].x * s + path->points[i].y * c) / TRIG_MAX_RATIO + offset.y; if(points_rot[i].x > bottom_left.x) bottom_left.x = points_rot[i].x; if(points_rot[i].x < top_right.x) top_right.x = points_rot[i].x; if(points_rot[i].y > bottom_left.y) bottom_left.y = points_rot[i].y; if(points_rot[i].y < top_right.y) top_right.y = points_rot[i].y; } // Create an array bitmap pebble v2 style (1 bit equals 1 pixel) int32_t bytes_per_row = (bottom_left.x - top_right.x + 1) / 8 + ((bottom_left.x - top_right.x + 1) % 8 == 0 ? 0 : 1); int32_t h = bottom_left.y - top_right.y + 1; uint8_t* pixels = malloc(bytes_per_row * h); memset(pixels, 0, bytes_per_row * h); // And draw the outline path in this 1 bit image GPoint prev_p = points_rot[path->num_points - 1]; GPoint p; for(uint32_t i=0; i<path->num_points; i++){ p = points_rot[i]; bmpDrawLine(pixels, bytes_per_row, prev_p.x - top_right.x, prev_p.y - top_right.y, p.x - top_right.x, p.y - top_right.y); prev_p = p; } free(points_rot); // Compute the starting point for the flow fill algorithm // TODO tobe improved GPoint start; start.x = (points_rot[0].x + points_rot[1].x) / 2; start.y = (points_rot[0].y + points_rot[1].y) / 2; if(points_rot[0].x < points_rot[1].x){ if(points_rot[0].y < points_rot[1].y){ start.x--; start.y++; } else { start.x++; start.y++; } } else { if(points_rot[0].y < points_rot[1].y){ start.x--; start.y--; } else { start.x++; start.y--; } } // Capture the frame buffer GBitmap* bitmap = graphics_capture_frame_buffer(ctx); // flood fill the gpath floodFill(bitmap, pixels, bytes_per_row, start, top_right, fill_color); // Release the frame buffer graphics_release_frame_buffer(ctx, bitmap); //Release the working variables free(pixels); }
void solveMaze() { //Reset maze to 0 initializeMaze(&maze); //We Know at the starting point, there's something behind us setN(&maze[0][0], 1); mouse.direction.x = 0; mouse.direction.y = -1; mouse.x = 0; mouse.y = 0; //Disable the mouse for now enableDrive(0); turnOnTimers(0, 0); int areWeSearching = UserInterfaceIntro(); //Does the user want to skip the search phase and load a maze from EEPROM if(areWeSearching) { /* SEARCH MAZE */ for(int i = 0; i < 10; i++) { turnOnLeds(7); _delay_ms(10); turnOnLeds(0); _delay_ms(90); } //Init Mouse enableDrive(1); turnOnTimers(1, 1); setDirection(0, 0); //Update Sensors updateSensors(); updateSensors(); updateWalls(); //Go Forward first block mouse.IR_LONG_CHECK_LEFT = 2; mouse.IR_LONG_CHECK_RIGHT = 2; straight(480, 0, mouse.maxVelocity, mouse.maxVelocity, mouse.acceleration, mouse.deceleration); mouse.x += mouse.direction.x; mouse.y -= mouse.direction.y; /* SEARCH */ InitialSearchRun(); //Search is Complete! updateWalls(); /* TURN AROUND */ mouse.rightMotor.stepCount = mouse.leftMotor.stepCount = 0; StopFromSpeedHalf(); mouse.rightMotor.stepCount = mouse.leftMotor.stepCount = 0; moveBackwards(); //Save Maze to EEPROM saveCurrentMaze(); writeMemByte(MOUSE_DIRECTION, firstTurn); mouse.rightMotor.stepCount = mouse.leftMotor.stepCount = 0; moveForwardHalf(); //Current Mouse Direction int dirx = mouse.direction.x; int diry = mouse.direction.y; //Reverse and go back mouse.direction.x = -dirx; mouse.direction.y = -diry; //Set Position to next block mouse.x += mouse.direction.x; mouse.y -= mouse.direction.y; /* RETURN SEARCH*/ ReturnSearchRun(); //Turn Around mouse.rightMotor.stepCount = mouse.leftMotor.stepCount = 0; StopFromSpeedHalf(); mouse.rightMotor.stepCount = mouse.leftMotor.stepCount = 0; moveBackwards(); //Save Maze to EEPROM saveCurrentMaze(); writeMemByte(MOUSE_DIRECTION, firstTurn); /* PICK UP AND PLACE MOUSE */ enableDrive(0); waitForButtonPressed(); } /* FAST RUN */ FastRun(); //Completed Search run, go back and search some more turnAroundInPlace(); floodFill(maze, firstTurn, mouse.x, mouse.y); /* RETURN */ ReturnSearchRun(); //Turn Around mouse.rightMotor.stepCount = mouse.leftMotor.stepCount = 0; StopFromSpeedHalf(); mouse.rightMotor.stepCount = mouse.leftMotor.stepCount = 0; moveBackwards(); //Save Maze to EEPROM saveCurrentMaze(); writeMemByte(MOUSE_DIRECTION, firstTurn); stopMouse(); while(!isButtonPushed(1)); printMaze(maze); }
bool Scraper::FindAllBMPs(const searchType type, HBITMAP hBmp, const double threshold, const int maxMatch, vector<MATCHPOINTS> &matches) { // Convert HBITMAP to Mat unique_ptr<Gdiplus::Bitmap> pBitmap; pBitmap.reset(Gdiplus::Bitmap::FromHBITMAP(hBmp, NULL)); Mat img = CGdiPlus::CopyBmpToMat(pBitmap.get()); pBitmap.reset(); cvtColor( img, img, CV_BGRA2BGR ); // Find right image group imageType iType = type==searchGoldStorage ? goldStorage : type==searchElixStorage ? elixStorage : type==searchDarkStorage ? darkStorage : type==searchLootCollector ? collector : type==searchLootBubble ? lootBubble : type==searchDonateButton ? donateButton : (imageType) 0; int iTypeIndex = -1; for (int i = 0; i < (int) imageGroups.size(); i++) if (imageGroups[i].iType == iType) iTypeIndex = i; if (iTypeIndex == -1) return false; // Scan through each Mat in this image group int count = 0; for (int i = 0; i < (int) imageGroups[iTypeIndex].mats.size(); i++) { // Get matches for this image Mat result( FindMatch(img, imageGroups[iTypeIndex].mats[i]) ); // Parse through matches in result set while (count < maxMatch) { double minVal, maxVal; Point minLoc, maxLoc; minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc); // Fill haystack with pure green so we don't match this same location rectangle(img, maxLoc, cv::Point(maxLoc.x + imageGroups[iTypeIndex].mats[i].cols, maxLoc.y + imageGroups[iTypeIndex].mats[i].rows), CV_RGB(0,255,0), 2); // Fill results array with lo vals, so we don't match this same location floodFill(result, maxLoc, 0, 0, Scalar(0.1), Scalar(1.0)); if (maxVal >= threshold && maxVal > 0) { // Check if this point is within 10 pixels of an existing match to avoid dupes bool alreadyFound = false; for (int k=0; k<count; k++) { if (DistanceBetweenTwoPoints((double) maxLoc.x, (double) maxLoc.y, (double) matches.at(k).x, (double) matches.at(k).y) < 10.0) { alreadyFound = true; break; } } // Add matched location to the vector if (alreadyFound == false) { MATCHPOINTS match; match.val = maxVal; match.x = maxLoc.x; match.y = maxLoc.y; matches.push_back(match); count++; } } else { break; } } if (count >= maxMatch) break; } return true; }
void Plane::fill() { floodFill(center); }
bool HandSplitterNew::compute(ForegroundExtractorNew& foreground_extractor, MotionProcessorNew& motion_processor, string name, bool visualize) { if (value_store.get_bool("first_pass", false) == false) { value_store.set_bool("first_pass", true); algo_name += name; } bool algo_name_found = false; for (String& algo_name_current : algo_name_vec_old) if (algo_name_current == algo_name) { algo_name_found = true; break; } LowPassFilter* low_pass_filter = value_store.get_low_pass_filter("low_pass_filter"); //------------------------------------------------------------------------------------------------------------------------ Mat image_find_contours = Mat::zeros(HEIGHT_SMALL, WIDTH_SMALL, CV_8UC1); for (BlobNew& blob : *foreground_extractor.blob_detector.blobs) if (blob.active) blob.fill(image_find_contours, 254); vector<vector<Point>> contours = legacyFindContours(image_find_contours); if (contours.size() == 0) return false; int complexity = 0; for (vector<Point>& contour : contours) { vector<Point> contour_approximated; approxPolyDP(Mat(contour), contour_approximated, 10, false); complexity += contour_approximated.size(); } //------------------------------------------------------------------------------------------------------------------------ int x_min = foreground_extractor.x_min_result; int x_max = foreground_extractor.x_max_result; int y_min = foreground_extractor.y_min_result; int y_max = foreground_extractor.y_max_result; float x_seed_vec0_max = value_store.get_float("x_seed_vec0_max"); float x_seed_vec1_min = value_store.get_float("x_seed_vec1_min"); int intensity_array[WIDTH_SMALL] { 0 }; for (BlobNew& blob : *foreground_extractor.blob_detector.blobs) if (blob.active) for (Point& pt : blob.data) ++intensity_array[pt.x]; vector<Point> hist_pt_vec; for (int i = 0; i < WIDTH_SMALL; ++i) { int j = intensity_array[i]; low_pass_filter->compute(j, 0.5, "histogram_j"); if (j < 10) continue; for (int j_current = 0; j_current < j; ++j_current) hist_pt_vec.push_back(Point(i, j_current)); } Point seed0 = Point(x_min, 0); Point seed1 = Point(x_max, 0); vector<Point> seed_vec0; vector<Point> seed_vec1; while (true) { seed_vec0.clear(); seed_vec1.clear(); for (Point& pt : hist_pt_vec) { float dist0 = get_distance(pt, seed0, false); float dist1 = get_distance(pt, seed1, false); if (dist0 < dist1) seed_vec0.push_back(pt); else seed_vec1.push_back(pt); } if (seed_vec0.size() == 0 || seed_vec1.size() == 0) break; Point seed0_new = Point(0, 0); for (Point& pt : seed_vec0) { seed0_new.x += pt.x; seed0_new.y += pt.y; } seed0_new.x /= seed_vec0.size(); seed0_new.y /= seed_vec0.size(); Point seed1_new = Point(0, 0); for (Point& pt : seed_vec1) { seed1_new.x += pt.x; seed1_new.y += pt.y; } seed1_new.x /= seed_vec1.size(); seed1_new.y /= seed_vec1.size(); if (seed0 == seed0_new && seed1 == seed1_new) break; seed0 = seed0_new; seed1 = seed1_new; } bool dual = false; if (seed_vec0.size() > 0 && seed_vec1.size() > 0) { x_seed_vec0_max = seed_vec0[seed_vec0.size() - 1].x; x_seed_vec1_min = seed_vec1[0].x; low_pass_filter->compute_if_smaller(x_seed_vec0_max, 0.5, "x_seed_vec0_max"); low_pass_filter->compute_if_larger(x_seed_vec1_min, 0.5, "x_seed_vec1_min"); value_store.set_float("x_seed_vec0_max", x_seed_vec0_max); value_store.set_float("x_seed_vec1_min", x_seed_vec1_min); value_store.set_bool("x_min_max_set", true); //------------------------------------------------------------------------------------------------------------------------ int width0 = x_seed_vec0_max - x_min; int width1 = x_max - x_seed_vec1_min; int width_min = min(width0, width1); float gap_size = x_seed_vec1_min - x_seed_vec0_max; low_pass_filter->compute_if_larger(gap_size, 0.1, "gap_size"); //------------------------------------------------------------------------------------------------------------------------ bool bool_complexity = complexity >= 15; bool bool_width_min = width_min >= 20; bool bool_gap_size = gap_size >= 5; bool bool_gap_order = x_seed_vec0_max < x_seed_vec1_min; dual = bool_gap_order && bool_width_min && (bool_gap_size || bool_complexity); } //------------------------------------------------------------------------------------------------------------------------ BlobNew* blob_max_size_left = NULL; BlobNew* blob_max_size_right = NULL; BlobNew* blob_max_size = NULL; for (BlobNew& blob : *foreground_extractor.blob_detector.blobs) { if (blob.x <= motion_processor.x_separator_middle && (blob_max_size_left == NULL || blob.count > blob_max_size_left->count)) blob_max_size_left = &blob; else if (blob.x > motion_processor.x_separator_middle && (blob_max_size_right == NULL || blob.count > blob_max_size_right->count)) blob_max_size_right = &blob; if (blob_max_size == NULL || blob.count > blob_max_size->count) blob_max_size = &blob; } //------------------------------------------------------------------------------------------------------------------------ int count_left = 0; int count_right = 0; int x_min_left = 9999; int x_max_left = 0; int x_min_right = 9999; int x_max_right = 0; for (BlobNew& blob : *foreground_extractor.blob_detector.blobs) if (blob.active) { for (Point& pt : blob.data) if (pt.x < motion_processor.x_separator_middle) { ++count_left; if (pt.x < x_min_left) x_min_left = pt.x; if (pt.x > x_max_left) x_max_left = pt.x; } else { ++count_right; if (pt.x < x_min_right) x_min_right = pt.x; if (pt.x > x_max_right) x_max_right = pt.x; } } int width_left = x_max_left - x_min_left; int width_right = x_max_right - x_min_right; //------------------------------------------------------------------------------------------------------------------------ bool reference_is_left = value_store.get_bool("reference_is_left", false); bool dual_old = value_store.get_bool("dual_old", dual); bool merge = value_store.get_bool("merge", false); if (!dual && dual_old) { float count_small = reference_is_left ? count_right : count_left; float count_large = reference_is_left ? count_left : count_right; if (count_small / count_large > 0.5) { merge = true; value_store.set_bool("merge", merge); } } dual_old = dual; value_store.set_bool("dual_old", dual_old); //------------------------------------------------------------------------------------------------------------------------ int reference_x_offset = value_store.get_int("reference_x_offset", 0); int reference_x_offset_blob = value_store.get_int("reference_x_offset_blob", 0); bool do_reset = value_store.get_bool("do_reset", false); if (dual || !algo_name_found || do_reset) { if (dual) { motion_processor.compute_x_separator_middle = false; set_value(&motion_processor.x_separator_middle, (x_seed_vec1_min + x_seed_vec0_max) / 2, 0, WIDTH_SMALL_MINUS); } reference_is_left = count_left > count_right; value_store.set_bool("reference_is_left", reference_is_left); if (!algo_name_found || do_reset) set_value(&motion_processor.x_separator_middle, motion_processor.x_separator_middle_median, 0, WIDTH_SMALL_MINUS); int reference_x = reference_is_left ? foreground_extractor.x_min_result : foreground_extractor.x_max_result; reference_x_offset = reference_x - motion_processor.x_separator_middle; value_store.set_int("reference_x_offset", reference_x_offset); int reference_x_blob = -1; if (reference_is_left && blob_max_size_left != NULL) reference_x_blob = blob_max_size_left->x_max; else if (!reference_is_left && blob_max_size_right != NULL) reference_x_blob = blob_max_size_right->x_min; if (reference_x_blob != -1) { reference_x_offset_blob = reference_x_blob - motion_processor.x_separator_middle; value_store.set_int("reference_x_offset_blob", reference_x_offset_blob); } merge = false; value_store.set_bool("merge", merge); do_reset = false; value_store.set_bool("do_reset", do_reset); } //------------------------------------------------------------------------------------------------------------------------ if (!dual && !merge) { int reference_x = reference_is_left ? foreground_extractor.x_min_result : foreground_extractor.x_max_result; int reference_x_blob = reference_is_left ? blob_max_size->x_max : blob_max_size->x_min; const int x_separator_middle_target = reference_x_blob - reference_x_offset_blob; const int x_separator_middle = motion_processor.x_separator_middle; const int i_increment = x_separator_middle_target > motion_processor.x_separator_middle ? 1 : -1; int cost = 0; for (int i = x_separator_middle; i != x_separator_middle_target; i += i_increment) for (int j = 0; j < HEIGHT_SMALL; ++j) if (foreground_extractor.image_foreground.ptr<uchar>(j, i)[0] > 0) ++cost; if ((float)cost / blob_max_size->count < 0.5) set_value(&motion_processor.x_separator_middle, x_separator_middle_target, 0, WIDTH_SMALL_MINUS); else { do_reset = true; value_store.set_bool("do_reset", do_reset); } } //------------------------------------------------------------------------------------------------------------------------ Point seed_left = value_store.get_point("seed_left", Point(x_min, 0)); Point seed_right = value_store.get_point("seed_right", Point(x_max, 0)); if (merge || dual) { seed_left = Point(0, 0); int seed_left_count = 0; for (BlobNew& blob : blobs_left) for (Point& pt : blob.data) { seed_left.x += pt.x; seed_left.y += pt.y; ++seed_left_count; } seed_right = Point(0, 0); int seed_right_count = 0; for (BlobNew& blob : blobs_right) for (Point& pt : blob.data) { seed_right.x += pt.x; seed_right.y += pt.y; ++seed_right_count; } if (seed_left_count > 0 && seed_right_count > 0) { seed_left.x /= seed_left_count; seed_left.y /= seed_left_count; seed_right.x /= seed_right_count; seed_right.y /= seed_right_count; vector<Point> seed_left_vec; vector<Point> seed_right_vec; while (true) { seed_left_vec.clear(); seed_right_vec.clear(); for (BlobNew& blob : *foreground_extractor.blob_detector.blobs) if (blob.active) for (Point& pt : blob.data) { float dist_left = get_distance(pt, seed_left, false); float dist_right = get_distance(pt, seed_right, false); if (dist_left < dist_right) seed_left_vec.push_back(pt); else seed_right_vec.push_back(pt); } if (seed_left_vec.size() > 0 && seed_right_vec.size() > 0) { Point seed_left_new = Point(0, 0); for (Point& pt : seed_left_vec) { seed_left_new.x += pt.x; seed_left_new.y += pt.y; } seed_left_new.x /= seed_left_vec.size(); seed_left_new.y /= seed_left_vec.size(); Point seed_right_new = Point(0, 0); for (Point& pt : seed_right_vec) { seed_right_new.x += pt.x; seed_right_new.y += pt.y; } seed_right_new.x /= seed_right_vec.size(); seed_right_new.y /= seed_right_vec.size(); if (seed_left.x == seed_left_new.x && seed_left.y == seed_left_new.y && seed_right.x == seed_right_new.x && seed_right.y == seed_right_new.y) { break; } seed_left = seed_left_new; seed_right = seed_right_new; } else break; } if (merge) set_value(&motion_processor.x_separator_middle, (seed_left.x + seed_right.x) / 2, 0, WIDTH_SMALL_MINUS); } } value_store.set_point("seed_left", seed_left); value_store.set_point("seed_right", seed_right); //------------------------------------------------------------------------------------------------------------------------ const int x_separator_middle = motion_processor.x_separator_middle; const int x_separator_middle_median = motion_processor.x_separator_middle_median; const int x_separator_left_median = motion_processor.x_separator_left_median; const int x_separator_right_median = motion_processor.x_separator_right_median; const int y_separator_down_median = motion_processor.y_separator_down_median; const int y_separator_up_median = motion_processor.y_separator_up_median; while (dual) { const int i_min = seed_left.x; const int i_max = seed_right.x; const int j_min = 0; const int j_max = y_separator_up_median; if (!(i_max > i_min && i_min >= 0 && i_max <= WIDTH_SMALL_MINUS)) break; Point pt0 = Point(i_min, 0); Point pt1 = Point(i_max, 0); Point pt2 = Point(x_separator_middle, j_max); //tip point if (pt2.y < 2 || i_max - i_min < 2) break; Mat image_triangle_fill = Mat::zeros(j_max + 1, WIDTH_SMALL, CV_8UC1); line(image_triangle_fill, pt0, pt2, Scalar(254), 1); line(image_triangle_fill, pt1, pt2, Scalar(254), 1); floodFill(image_triangle_fill, Point(x_separator_middle, 0), Scalar(254)); for (int i = i_min; i <= i_max; ++i) for (int j = j_min; j <= j_max; ++j) if (image_triangle_fill.ptr<uchar>(j, i)[0] > 0) motion_processor.fill_image_background_static(i, j, motion_processor.image_ptr); break; } //------------------------------------------------------------------------------------------------------------------------ x_min_result_right = 9999; x_max_result_right = -1; y_min_result_right = 9999; y_max_result_right = -1; x_min_result_left = 9999; x_max_result_left = -1; y_min_result_left = 9999; y_max_result_left = -1; blobs_right.clear(); blobs_left.clear(); for (BlobNew& blob : *foreground_extractor.blob_detector.blobs) if (blob.active) { if (blob.x > motion_processor.x_separator_middle) { if (blob.x_min < x_min_result_right) x_min_result_right = blob.x_min; if (blob.x_max > x_max_result_right) x_max_result_right = blob.x_max; if (blob.y_min < y_min_result_right) y_min_result_right = blob.y_min; if (blob.y_max > y_max_result_right) y_max_result_right = blob.y_max; blobs_right.push_back(blob); } else { if (blob.x_min < x_min_result_left) x_min_result_left = blob.x_min; if (blob.x_max > x_max_result_left) x_max_result_left = blob.x_max; if (blob.y_min < y_min_result_left) y_min_result_left = blob.y_min; if (blob.y_max > y_max_result_left) y_max_result_left = blob.y_max; blobs_left.push_back(blob); } } //------------------------------------------------------------------------------------------------------------------------ if (visualize) { Mat image_visualization = Mat::zeros(HEIGHT_SMALL, WIDTH_SMALL, CV_8UC1); for (BlobNew& blob : *foreground_extractor.blob_detector.blobs) if (blob.active) blob.fill(image_visualization, 254); line(image_visualization, Point(x_separator_left_median, 0), Point(x_separator_left_median, 999), Scalar(254), 1); line(image_visualization, Point(x_separator_right_median, 0), Point(x_separator_right_median, 999), Scalar(254), 1); line(image_visualization, Point(x_separator_middle, 0), Point(x_separator_middle, 999), Scalar(254), 1); line(image_visualization, Point(0, y_separator_down_median), Point(999, y_separator_down_median), Scalar(254), 1); line(image_visualization, Point(0, y_separator_up_median), Point(999, y_separator_up_median), Scalar(254), 1); imshow("image_visualizationsdlkfjhasdf" + name, image_visualization); } if (blobs_right.size() > 0 || blobs_left.size() > 0) { algo_name_vec.push_back(algo_name); return true; } return false; }