Ejemplo n.º 1
0
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;

}
Ejemplo n.º 3
0
/*******************************************************************************
* 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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
void colorFill( int x, int y, COLOR fillColor )
{
	//boundaryFill(x, y, fillColor);
	floodFill(x, y, fillColor);
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
}