コード例 #1
0
ファイル: TableObjectDetector.cpp プロジェクト: bdol/eyetrack
/**
 * Takes a 3d plane and draws its transform on the given image.
 */
void TableObjectDetector::drawTablePlane(Mat img, Mat* plane, KinectCalibParams* calib) {
    Point pt[1][4];

    Mat R = calib->getR();
    Mat Rt; transpose(R, Rt);
    Mat T = calib->getT();
    Mat K = calib->getRGBIntrinsics();

    for (int i=0; i<4; i++) {
        Mat p = plane->col(i+1);
        
        // Apply extrinsics
        Mat prgbw = Rt*p - T;
        // Calculate transform to RGB plane
        Mat prgb_hat = K*prgbw;
        Point prgb((int)(prgb_hat.at<double>(0)/prgb_hat.at<double>(2)),
                      (int)(prgb_hat.at<double>(1)/prgb_hat.at<double>(2)));

        pt[0][i] = prgb;
    }
    
    const Point* ppt[1] = {pt[0]};
    int npt[] = {4};
    fillPoly(img, ppt, npt, 1, Scalar(255, 0, 255), 8);
    
}
コード例 #2
0
ファイル: BodyModel.cpp プロジェクト: chenww05/M2M
void BodyModel::drawTriangle(Point p1, Point p2, Point p3)
{
    Point rook_points[1][3];
    rook_points[0][0] = p1;
    rook_points[0][1] = p2;
    rook_points[0][2] = p3;
    const Point* ppt[1] = { rook_points[0] };
    int npt[] = { 3 };
    fillPoly(_mask, ppt, npt, 1, Scalar(255, 255, 255), 8);
}
コード例 #3
0
ファイル: BodyModel.cpp プロジェクト: chenww05/M2M
void BodyModel::drawPolygon(Point upperRight, Point upperLeft, Point lowerRight, Point lowerLeft)
{
    Point rook_points[1][4];
    rook_points[0][0] = upperRight;
    rook_points[0][3] = upperLeft;
    rook_points[0][1] = lowerRight;
    rook_points[0][2] = lowerLeft;
    const Point* ppt[1] = { rook_points[0] };
    int npt[] = { 4 };
    fillPoly(_mask, ppt, npt, 1, Scalar(255, 255, 255), 8);
}
コード例 #4
0
ファイル: drawwindow.cpp プロジェクト: GunnarHorve/painter
  void drawPolyPoints() {
    int n = poly_points.size();
    int npt[] = { n };

    /** Create some points */
    cv::Point **points = new cv::Point*[1];
    points[0]=new cv::Point[n];

    for (int i=0; i<n; i++) {
      points[0][i] = poly_points[i];
    }
    const cv::Point* ppt[1] = { points[0] };
 
    fillPoly( grid, ppt, npt, 1, pen_color, line_type);
    delete [] points[0];
    delete [] points;
  }
コード例 #5
0
ファイル: BodyModel.cpp プロジェクト: chenww05/M2M
void BodyModel::drawBodyShape(Point upperRight, Point upperLeft, Point lowerRight, Point lowerLeft, int max)
{
    Point rook_points[1][8];
    rook_points[0][0] = upperRight;
    rook_points[0][7] = upperLeft;
    rook_points[0][3] = lowerRight;
    rook_points[0][4] = lowerLeft;
    
    rook_points[0][2] = ( upperRight + lowerRight ) / 2;
    rook_points[0][1] = ( upperRight + rook_points[0][2] ) / 2 + Point(max,  - 2 * abs(max));
    
    rook_points[0][5] = ( upperLeft + lowerLeft ) / 2;
    rook_points[0][6] = ( upperLeft + rook_points[0][5] ) / 2 + Point(- max, 0);
    const Point* ppt[1] = { rook_points[0] };
    int npt[] = { 8 };
    fillPoly(_mask, ppt, npt, 1, Scalar(255, 255, 255), 8);
}
コード例 #6
0
// === FUNCTION ======================================================================
// Name: get_masked_frame
// Description: Masks the frame based on slope and roi. Mask returned by pointer.
// =====================================================================================
cv::Mat get_masked_frame ( cv::Rect roi, double slope, cv::Mat* frame, cv::Mat* mask )
{
    cv::Point corners[1][4];
    //Set the frame
    *mask=cv::Mat::zeros( frame->size(), CV_8UC1 );
    cv::Mat masked_frame;
    if( slope==0 )
    {
        // TODO: Could use direction handling here.
        corners[0][0] = roi.br();
        corners[0][1] = cv::Point( frame->cols, roi.y+roi.height );
        corners[0][2] = corners[0][1]-cv::Point( 0, roi.height );
        corners[0][3] = corners[0][0]-cv::Point( 0, roi.height );
    }
    else if( isinf( slope ) )
    {
        {
            corners[0][0] = cv::Point( roi.x, frame->rows );
            corners[0][1] = cv::Point( roi.x, roi.y+roi.height);
        }
        {
            corners[0][0] = roi.tl();
            corners[0][1] = cv::Point( roi.x, 0 );
        }
        corners[0][2] = corners[0][1]+cv::Point( roi.width, 0);
        corners[0][3] = corners[0][0]+cv::Point( roi.width, 0 );
    }
    else
    {
        corners[0][0].x = ( int ) ( (frame->rows + slope*roi.x-roi.y)/slope );
        corners[0][0].y = frame->rows;
        corners[0][1] = cv::Point( ( int )( (-roi.y + slope * roi.x ) / slope ), 0 );
        corners[0][2] = corners[0][1] + cv::Point(roi.width, 0);
        corners[0][3] = corners[0][0] + cv::Point(roi.width, 0);
    }

    // This is weird, but follows OpenCV docs.
    const cv::Point* ppt[1] = { corners[0] };
    const int npt[] = { 4 };

    fillPoly( *mask, ppt, npt, 1, 255 );
    frame->copyTo(masked_frame, *mask);
    return masked_frame;
}	// ----- end of function get_masked_frame ----- 
コード例 #7
0
void RoadDetection::drawRoadShape(Mat frame, vector<Point> points, Scalar color, double alpha)
{
	Mat copy;
	Point shapePoints[1][3];
	int npt[] = { 3 };

	if (points.size() <= 0)
	{
		return;
	}

	for (size_t i = 0; i < points.size(); i++)
	{
		shapePoints[0][i] = points[i];
	}
		
	const Point* ppt[1] = { shapePoints[0] };
	frame.copyTo(copy);

	fillPoly(copy, ppt, npt, 1, color, CV_AA);
	addWeighted(copy, alpha, frame, 1.0 - alpha, 0.0, frame);
}
コード例 #8
0
void FieldLineDetector::createThresholdedImg(Mat& src)
{
	vector<vector<cv::Point> > cont;
	vector<vector<cv::Point> > contPoly;
	vector<Vec4i> hierarchy;
	Mat imgBwInv;
	imgThres = threshold(src);

	// find large contours and remove them from thresholded image
	bitwise_not(imgThres, imgBwInv);
	findContours(imgBwInv, cont, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE,
			cv::Point(0, 0));
	for (int i = 0; i < cont.size(); i++)
	{
		double area = contourArea(cont[i]);
		if (area > 100000)
		{
			contPoly.push_back(cont[i]);
		}
	}
	fillPoly(imgThres, contPoly, Scalar(255, 255, 255));
	imshow("thres", imgThres);
}
コード例 #9
0
ファイル: cv.cpp プロジェクト: Jiaran/MapReduce
void drawTriangle(int mx, int my, int x, int y, Mat img){
	int thickness = 1;
  	int lineType = 8;
	int wide = WIDE/mx;
  	int height = HEIGHT/my;
	Point center=getCenter(mx,my,x,y);

  /** Create some points */
  Point rook_points[1][3];
  rook_points[0][0] = Point( center.x, center.y-(height/2-5) );
  rook_points[0][1] = Point( center.x-(wide/2-5), center.y+(height/2-5) );
  rook_points[0][2] = Point( center.x+(wide/2-5), center.y+(height/2-5) );

  const Point* ppt[1] = { rook_points[0] };
  int npt[] = { 3 };

  fillPoly( img,
            ppt,
            npt,
            thickness,
            Scalar( 255, 255, 255 ),
            lineType ); 
}
コード例 #10
0
ファイル: modelmaker.cpp プロジェクト: biotracking/biotrack
void ModelMaker::extractModel(cv::Mat origframe)
{
    //       qDebug()<<"Frame is"<<frame.empty();
    for(int i = 0; i < centroids.size(); i++) {
        
        Mat subtractedframe(origframe);
        subtractedframe = subtractBack(origframe);
        Mat polymask = subtractedframe.clone();
        
        //                cv::cvtColor(frameMat, frameMat, CV_BGR2BGRA);
        
        //                cv::cvtColor(polymask, polymask, CV_BGR2BGRA);
        
        
        //cv::rectangle(mask, Point( 0, 0 ), Point( mask.cols, mask.rows), Scalar( 0, 255,0,255 ),-1, 8 ); //Fill all mask in
        
        polymask.setTo(Scalar(0,0,0,0));
        //Polgon Masking
        polygon = paintCanvas->polygons.at(i);
        
        Point poly_points[polygon.size()];
        
        //Find point furthest from center
        Point furthest = Point(paintCanvas->centerPoint.x()*xscale,paintCanvas->centerPoint.y()*yscale);  //set to center
        
        int scaledcenterx = paintCanvas->centerPoint.x()*xscale;
        int scaledcentery = paintCanvas->centerPoint.y()*yscale;
        int scaledheadx= paintCanvas->headPoint.x()*xscale;
        int scaledheady=paintCanvas->headPoint.y()*yscale;
        
        
        float biggestdistancesquared=0;
        
        
        for(int j=0;j<polygon.size();j++)
        {
            poly_points[j]=Point(xscale*polygon.at(j).x(), yscale*polygon.at(j).y());
            
            Point candidate = Point(xscale*polygon.at(j).x(), yscale*polygon.at(j).y());
            float distancecandidatesquared;
            //Find furthest
            distancecandidatesquared= (candidate.x - scaledcenterx)*(candidate.x - scaledcenterx) + (candidate.y - scaledcentery)*(candidate.y - scaledcentery);
            if(distancecandidatesquared>biggestdistancesquared){
                biggestdistancesquared=distancecandidatesquared;
                qDebug()<<"biggcandidate x "<<candidate.x <<"  y "<<candidate.y << "    distance ="<<biggestdistancesquared;
                
            }
            
            
            
        }
        
        const Point* ppt[1] = { poly_points };
        int npt[] = { polygon.size() };
        
        
        
        fillPoly( polymask,
                  ppt,
                  npt,
                  1,
                  Scalar( 255, 255,255,255 ),
                  
                  8,
                  0);
        
        
        
        //Debug
        //                                cv::circle(origframe,cv::Point(scaledcenterx,scaledcentery),1,Scalar(255,255,255,255),2);
        //                                cv::circle(origframe,cv::Point(scaledheadx,scaledheady),1,Scalar(255,0,255, 254),2);
        
        //cv::circle(polymask,cv::Point(scaledcenterx,scaledcentery),1,Scalar(255,255,255,255),2);
        //  cv::circle(polymask,cv::Point(scaledheadx,scaledheady),1,Scalar(255,0,255, 254),2);
        
        //  cv::circle(subtractedframe,cv::Point(scaledcenterx,scaledcentery),1,Scalar(255,255,255,255),2);
        //  cv::circle(subtractedframe,cv::Point(scaledheadx,scaledheady),1,Scalar(255,0,255, 254),2);
        
        
        
        //background subtraction: take original image, apply background as a mask, save over original
        //bitwise_and(subtractedframe, polymask, subtractedframe);
        
        qDebug()<<"Roi "<<x1<<"  "<<y1<<"  "<<x2<<"  "<<y2<<"  ";
        
        
        cv::cvtColor(polymask,polymask, CV_RGB2GRAY);
        
        
        //Full alpha mask = polygon selection (a =200) + BG subtracted organism (a= 255) + Center Mark ( a = 250) + head mark (a = 240)
        //Set Head to alpha=240
        //Set Center to Alpha = 250
        //Everything inside mask == alpha 200
        //Everything outside alpha=100;
        //BG subtracted ant = 255
        
        Mat maskedsubtraction;
        subtractedframe.copyTo(maskedsubtraction,polymask); // note that m.copyTo(m,mask) will have no masking effect
        cvtColor(maskedsubtraction, maskedsubtraction,CV_BGR2GRAY);
        polymask = polymask+155;   //255 moves to 255, 0 moves to 155
        polymask = polymask - 55;  //255 moves to 200, 155 moves to 100
        maskedsubtraction = polymask+maskedsubtraction;
        
        cv::circle(maskedsubtraction,cv::Point(scaledcenterx,scaledcentery),1,Scalar(250),2); //Encode the Center
        cv::circle(maskedsubtraction,cv::Point(scaledheadx,scaledheady),1,Scalar(240),2); //encode the head
        
        Mat bgr;
        bgr=origframe.clone();
        
        Mat alpha;
        maskedsubtraction.copyTo(alpha);
        Mat bgra;
        cvtColor(origframe, bgra,CV_BGR2BGRA); //Copy the origframe, we'll write over it next
        
        
        
        
        // forming array of matrices is quite efficient operations,
        // because the matrix data is not copied, only the headers
        Mat in[] = { bgr, alpha };
        // BGRa[0] -> bgr[0], BGRa[1] -> bgr[1],
        // BGRa[2] -> bgr[2], BGRa[3] -> alpha[0]
        int from_to[] = { 0,0,  1,1,  2,2,  3,3 };
        mixChannels( in, 2, &bgra, 1, from_to, 4 ); // input array, number of files in input array, destination, number of files in destination, from-to array, number of pairs in from-to
        
        
        
        QString ext = ".png";
        // QString fullframe = savepath+paintCanvas->polyNames.at(i)+"_"+QString::number(centroids[i].x())+"_"+QString::number(centroids[i].y())+"_"+QString::number(currentFrame)+ext;
        QString modelfilename = savepath+paintCanvas->polyNames.at(i)+"_f"+QString::number(currentFrame)+ext;
        
        //DEBUG IMAGES
        /*
              imwrite(modelfilename.toStdString()+"_subtraction",subtractedframe);
                imwrite(modelfilename.toStdString()+"_polymask",polymask);
                imwrite(modelfilename.toStdString()+"_alpha",alpha);
        */
        
        
        
        //save out Model
        
        //Full Keyframe
//        imwrite(modelfilename.toStdString()+"_keyframe",bgra); //Disabled for now
        
        qDebug()<<"Saved out: "<<modelfilename;
        
        //***Crop and Rotate ***//
        qDebug()<<"crop centered on  "<<scaledcenterx<<"  "<<scaledcentery;
        //crop the frame based on ROI
        Point2f src_center(scaledcenterx, scaledcentery);
        //To do this correctly use getRectSubPix instead of frameMat(MYROI) method
        // getRectSubPix only works with certain image formats (this is undocumented in opencv : P
        // so we have to do that cutting and mixing again!
        getRectSubPix(bgr, cv::Size(sqrt(biggestdistancesquared)*2,sqrt(biggestdistancesquared)*2), src_center, bgr);
        getRectSubPix(alpha, cv::Size(sqrt(biggestdistancesquared)*2,sqrt(biggestdistancesquared)*2), src_center, alpha);
        
        Mat bgracropped;
        cvtColor(bgr, bgracropped,CV_BGR2BGRA); //Copy the origframe, we'll write over it next
        Mat inagain[] = { bgr, alpha };
        int from_to2[] = { 0,0,  1,1,  2,2,  3,3 };
        
        //Note: the height and width dimensions have to be the same for the inputs and outputs
        mixChannels( inagain, 2, &bgracropped, 1, from_to2, 4 ); // input array, number of files in input array, destination, number of files in destination, from-to array, number of pairs in from-to
        
        
        //rotate the cropped frame about the center of the cropped frame.
        qDebug()<<"Rotate that image  "<<angle;
        bgracropped = rotateImage(bgracropped, angle);//Rotate full image about this center
        
        //after I rotate clear the global angle
        angle =0;
        //debug
        angle=-1;
        
        

        // Save the Nicely Rotated and Cropped Model File
        imwrite(modelfilename.toStdString(),bgracropped);
        
        
        centroids.clear();
        maxXY.clear();
        minXY.clear();
        paintCanvas->polyNames.clear();
        paintCanvas->polygons.clear();
        paintCanvas->masks.pop_back();
        polyinfo = "Polygon cleared";
        paintCanvas->temp.clear();
        ui->statusBar->showMessage(polyinfo,2000);
        paintCanvas->replyMask = replyNull;
        capture.set(CV_CAP_PROP_POS_FRAMES,(double)currentFrame);
    }
    
    
}
コード例 #11
0
ファイル: main.cpp プロジェクト: AMBITIONBIN/depthjs
Scalar refineSegments(const Mat& img, 
					  Mat& mask, 
					  Mat& dst, 
					  vector<Point>& contour,
					  vector<Point>& second_contour,
					  Point2i& previous)
{
	//    int niters = 3;
    
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    
    Mat temp;
    
	blur(mask, temp, Size(11,11));
	temp = temp > 85.0;
	
    findContours( temp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );
	
	if(dst.data==NULL)
		dst = Mat::zeros(img.size(), CV_8UC1);
	else
		dst.setTo(Scalar(0));
    
    if( contours.size() == 0 )
        return Scalar(-1,-1);
	
    // iterate through all the top-level contours,
    // draw each connected component with its own random color
    int idx = 0, largestComp = -1, secondlargest = -1;
    double maxWArea = 0, maxJArea = 0;
    vector<double> justarea(contours.size());
	vector<double> weightedarea(contours.size());
	
	//    for( ; idx >= 0; idx = hierarchy[idx][0] )
	for (; idx<contours.size(); idx++)
    {
        const vector<Point>& c = contours[idx];
		Scalar _mean = mean(Mat(contours[idx]));
		justarea[idx] = fabs(contourArea(Mat(c)));
		weightedarea[idx] = fabs(contourArea(Mat(c))) / 
		((previous.x >- 1) ? (1.0 + norm(Point(_mean[0],_mean[1])-previous)) : 1.0);	//consider distance from last blob
    }
	for (idx = 0; idx<contours.size(); idx++) {
		if( weightedarea[idx] > maxWArea )
        {
            maxWArea = weightedarea[idx];
            largestComp = idx;
        }
	}
	for (idx = 0; idx < contours.size(); idx++) {
		if ( justarea[idx] > maxJArea && idx != largestComp ) {
			maxJArea = justarea[idx];
			secondlargest = idx;
		}
	}
	
    Scalar color( 255 );
	//	cout << "largest cc " << largestComp << endl;
	//   drawContours( dst, contours, largestComp, color, CV_FILLED); //, 8, hierarchy );
	//	for (idx=0; idx<contours[largestComp].size()-1; idx++) {
	//		line(dst, contours[largestComp][idx], contours[largestComp][idx+1], color, 2);
	//	
	if(largestComp >= 0) {
		//find top-left values
		int maxx = -INT_MAX,miny = INT_MAX;
		int num = contours[largestComp].size();
		for (int i=0; i<num; i++) {
			if(contours[largestComp][i].x > maxx) maxx = contours[largestComp][i].x;
			if(contours[largestComp][i].y < miny) miny = contours[largestComp][i].y;
		}
		
		//crop contour to 150x150 "window"
		vector<Point> newblob = contours[largestComp];
//		int maxxp150 = MAX(maxx-200,0),minyp150 = MIN(miny+170,480);
//				
//		for (int i=0; i<num; i++) {
//			Point _p = contours[largestComp][i];
//			if(_p.x > maxxp150 && _p.y < minyp150) newblob.push_back(_p);
//				else newblob.push_back(Point(MAX(_p.x,maxxp150),MIN(_p.y,minyp150)));
//		}
		
		Point* pts = &(newblob[0]);
		num = newblob.size();
		fillPoly(dst, (const Point**)(&pts), &num, 1, color);
		
		Scalar b = mean(Mat(newblob)); //center of the blob
		b[0] += 40; b[1] -= 40;
		b[2] = justarea[largestComp];
		
		contour.clear();
		contour = newblob;
		
		second_contour.clear();
		if(secondlargest >= 0) {
			second_contour = contours[secondlargest];
			b[3] = maxJArea;
		}
		
		previous.x = b[0]; previous.y = b[1];
		return b;
	} else
		return Scalar(-1,-1);
	
}
コード例 #12
0
ファイル: platelines.cpp プロジェクト: psaintjust/openalpr
  void PlateLines::processImage(Mat inputImage, vector<TextLine> textLines, float sensitivity)
  {
    if (this->debug)
      cout << "PlateLines findLines" << endl;

    timespec startTime;
    getTimeMonotonic(&startTime);


    // Ignore input images that are pure white or pure black
    Scalar avgPixelIntensity = mean(inputImage);
    if (avgPixelIntensity[0] >= 252)
      return;
    else if (avgPixelIntensity[0] <= 3)
      return;

    // Do a bilateral filter to clean the noise but keep edges sharp
    Mat smoothed(inputImage.size(), inputImage.type());
    adaptiveBilateralFilter(inputImage, smoothed, Size(3,3), 45, 45);


    int morph_elem  = 2;
    int morph_size = 2;
    Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );


    Mat edges(inputImage.size(), inputImage.type());
    Canny(smoothed, edges, 66, 133);

    // Create a mask that is dilated based on the detected characters


    Mat mask = Mat::zeros(inputImage.size(), CV_8U);

    for (unsigned int i = 0; i < textLines.size(); i++)
    {
      vector<vector<Point> > polygons;
      polygons.push_back(textLines[i].textArea);
      fillPoly(mask, polygons, Scalar(255,255,255));
    }



    dilate(mask, mask, getStructuringElement( 1, Size( 1 + 1, 2*1+1 ), Point( 1, 1 ) ));
    bitwise_not(mask, mask);

    // AND canny edges with the character mask
    bitwise_and(edges, mask, edges);


    vector<PlateLine> hlines = this->getLines(edges, sensitivity, false);
    vector<PlateLine> vlines = this->getLines(edges, sensitivity, true);
    for (unsigned int i = 0; i < hlines.size(); i++)
      this->horizontalLines.push_back(hlines[i]);
    for (unsigned int i = 0; i < vlines.size(); i++)
      this->verticalLines.push_back(vlines[i]);

    // if debug is enabled, draw the image
    if (this->debug)
    {
      Mat debugImgHoriz(edges.size(), edges.type());
      Mat debugImgVert(edges.size(), edges.type());
      edges.copyTo(debugImgHoriz);
      edges.copyTo(debugImgVert);
      cvtColor(debugImgHoriz,debugImgHoriz,CV_GRAY2BGR);
      cvtColor(debugImgVert,debugImgVert,CV_GRAY2BGR);

      for( size_t i = 0; i < this->horizontalLines.size(); i++ )
      {
        line( debugImgHoriz, this->horizontalLines[i].line.p1, this->horizontalLines[i].line.p2, Scalar(0,0,255), 1, CV_AA);
      }

      for( size_t i = 0; i < this->verticalLines.size(); i++ )
      {
        line( debugImgVert, this->verticalLines[i].line.p1, this->verticalLines[i].line.p2, Scalar(0,0,255), 1, CV_AA);
      }

      vector<Mat> images;
      images.push_back(debugImgHoriz);
      images.push_back(debugImgVert);

      Mat dashboard = drawImageDashboard(images, debugImgVert.type(), 1);
      displayImage(pipelineData->config, "Hough Lines", dashboard);
    }

    if (pipelineData->config->debugTiming)
    {
      timespec endTime;
      getTimeMonotonic(&endTime);
      cout << "Plate Lines Time: " << diffclock(startTime, endTime) << "ms." << endl;
    }

  }
コード例 #13
0
ファイル: mainwindow.cpp プロジェクト: sh1r0/SEAcret
void MainWindow::mouseHandler(int event, int x, int y, int flags, void* param)
{
    MainWindow* window = (MainWindow*) param;
    if (window->mode == 3) {
        x = bound(x, window->R, window->_src.cols-1-window->R);
        y = bound(y, window->R, window->_src.rows-1-window->R);
    }
    else {
        x = bound(x, 0, window->_src.cols-1);
        y = bound(y, 0, window->_src.rows-1);
    }

    // user press left button
    if (event == CV_EVENT_LBUTTONDOWN && !window->drag) {
        if (window->mode == 1)
            window->point = Point(x, y);
        else if (window->mode == 2) {
            window->points.clear();
            window->points.push_back(Point(x, y));
        }
        else if (window->mode == 3) {
            Rect box = Rect(x-window->R, y-window->R, 1+window->R*2, 1+window->R*2);
            Mat temp;
            medianBlur(window->_dst(box), temp, window->kernel);
            temp.copyTo(window->_dst(box), window->round_mask);
            window->round_mask.copyTo(window->zone(box), window->round_mask);
            imshow("Image", window->_dst);
        }
        window->drag = true;
    }

    // user drag the mouse
    if (event == CV_EVENT_MOUSEMOVE && window->drag) {
        Mat temp = window->_dst.clone();

        if (window->mode == 1)
            rectangle(temp, window->point, Point(x, y), CV_RGB(255, 0, 0), 2, 8, 0);
        else if (window->mode == 2) {
            window->pts = (const Point*)Mat(window->points).data;
            window->npts = window->points.size();
            window->points.push_back(Point(x, y));
            polylines(temp, &window->pts, &window->npts, 1, false, Scalar(0,0,255), 2, 8, 0);
        }
        else if (window->mode == 3) {
            Rect box = Rect(x-window->R, y-window->R, 1+window->R*2, 1+window->R*2);
            Mat temp;
            medianBlur(window->_dst(box), temp, window->kernel);
            temp.copyTo(window->_dst(box), window->round_mask);
            window->round_mask.copyTo(window->zone(box), window->round_mask);
            imshow("Image", window->_dst);
            return;
        }

        imshow("Image", temp);
    }

    // user release left button
    if (event == CV_EVENT_LBUTTONUP && window->drag) {
        if (window->mode == 1) {
            Point temp(window->point);
            window->point.x = min(x, temp.x);
            x = max(x, temp.x);
            window->point.y = min(y, temp.y);
            y = max(y, temp.y);

            rectangle(window->zone, window->point, Point(x, y), Scalar(255), CV_FILLED, 8, 0);
            Rect box = Rect(window->point.x, window->point.y, x - window->point.x, y - window->point.y);

            if (window->style == 1) {
                medianBlur(window->_dst(box), window->_dst(box), window->kernel);
                medianBlur(window->_dst(box), window->_dst(box), window->kernel);
            }
            else {
                Mat mask = Mat::zeros(window->_src.size(), CV_8UC1);
                rectangle(mask, window->point, Point(x, y), CV_RGB(255, 255, 255), CV_FILLED, 8, 0);
                inpaint(window->_dst, mask, window->_dst, 5, INPAINT_TELEA);
            }
        }
        else if (window->mode == 2) {
            Rect box = boundingRect(window->points);
            vector< vector<Point> > contour;
            contour.push_back(window->points);
            Mat mask = Mat::zeros(window->_src.size(), CV_8UC1);
            fillPoly(mask, contour, Scalar(255));
            fillPoly(window->zone, contour, Scalar(255));

            if (window->style == 1) {
                Mat temp;
                medianBlur(window->_dst(box), temp, window->kernel);
                medianBlur(temp, temp, window->kernel);
                temp.copyTo(window->_dst(box), mask(box));
            }
            else
                inpaint(window->_dst, mask, window->_dst, 5, INPAINT_TELEA);
        }

        imshow("Image", window->_dst);
        window->drag = false;
    }

    // user click right button: reset all
    if (event == CV_EVENT_RBUTTONUP) {
        window->_dst = window->_src.clone();
        window->zone = Mat::zeros(window->_src.size(), CV_8UC1);
        window->drag = false;
        imshow("Image", window->_dst);
    }
}