2012-04-15 73 views
17

Tôi cố gắng để vẽ vectơ vận tốc như trong MATLAB chúng tôi sử dụng "rung động" chức năng http://www.mathworks.com/help/techdoc/ref/quiver.htmlOpenCV Làm thế nào để Vẽ vectơ vận tốc như mũi tên trong việc sử dụng hình ảnh đơn tĩnh

Tôi cần phải cổng cùng phương pháp trong C++ sử dụng thư viện OpenCV.

Tôi đã nghe nói Có một vài phương pháp dòng chảy quang học, tức là Lucas và Kanade (cvCalOpticalFlowLK) hoặc Horn và Schunck (cvCalOpticalFlowHS) hoặc phương pháp Matching Block (cvCalOpticalFlowBM)

nhưng tất cả các chức năng này có hai hình ảnh, trong khi tôi cần phải sử dụng một hình ảnh bởi vì tôi đang làm việc trên dấu vân tay.

Vui lòng giúp tôi ...

[Chỉnh sửa] Giải pháp phát hiện

void cvQuiver(IplImage*Image,int x,int y,int u,int v,CvScalar Color, 
              int Size,int Thickness){ 
cv::Point pt1,pt2; 
double Theta; 
double PI = 3.1416; 

if(u==0) 
    Theta=PI/2; 
else 
    Theta=atan2(double(v),(double)(u)); 

pt1.x=x; 
pt1.y=y; 

pt2.x=x+u; 
pt2.y=y+v; 

cv::line(Image,pt1,pt2,Color,Thickness,8); //Draw Line 


Size=(int)(Size*0.707); 


if(Theta==PI/2 && pt1.y > pt2.y) 
    { 
    pt1.x=(int)(Size*cos(Theta)-Size*sin(Theta)+pt2.x); 
    pt1.y=(int)(Size*sin(Theta)+Size*cos(Theta)+pt2.y); 
    cv::line(Image,pt1,pt2,Color,Thickness,8); //Draw Line 

    pt1.x=(int)(Size*cos(Theta)+Size*sin(Theta)+pt2.x); 
    pt1.y=(int)(Size*sin(Theta)-Size*cos(Theta)+pt2.y); 
    cv::line(Image,pt1,pt2,Color,Thickness,8); //Draw Line 
    } 
else{ 
    pt1.x=(int)(-Size*cos(Theta)-Size*sin(Theta)+pt2.x); 
    pt1.y=(int)(-Size*sin(Theta)+Size*cos(Theta)+pt2.y); 
    cv::line(Image,pt1,pt2,Color,Thickness,8); //Draw Line 

    pt1.x=(int)(-Size*cos(Theta)+Size*sin(Theta)+pt2.x); 
    pt1.y=(int)(-Size*sin(Theta)-Size*cos(Theta)+pt2.y); 
    cv::line(Image,pt1,pt2,Color,Thickness,8); //Draw Line 
    } 

} 

Trả lời

29

Tôi là loại hoàn thành câu trả lời hiện tại ở đây, không đạt được kích thước phù hợp với từng mũi tên của mũi tên. MATLAB thực hiện nó theo cách mà khi một mũi tên gần như là một dấu chấm, nó không có bất kỳ mẹo nào, trong khi các mũi tên dài nó cho thấy một mẹo lớn, như hình ảnh sau đây cho thấy.

enter image description here

Để có được hiệu ứng này, chúng ta cần phải chuẩn hóa "kích thước tip" của mỗi mũi tên lên trên phạm vi chiều dài mũi tên. Các mã sau hiện các trick

double l_max = -10; 

    for (int y = 0; y < img_sz.height; y+=10)               // First iteration, to compute the maximum l (longest flow) 
    { 
     for (int x = 0; x < img_sz.width; x+=10) 
     { 
      double dx = cvGetReal2D(velx, y, x);              // Gets X component of the flow 
      double dy = cvGetReal2D(vely, y, x);              // Gets Y component of the flow 

      CvPoint p = cvPoint(x, y); 

      double l = sqrt(dx*dx + dy*dy);                // This function sets a basic threshold for drawing on the image 

      if(l>l_max) l_max = l; 
     } 
    } 


    for (int y = 0; y < img_sz.height; y+=10) 
{ 
    for (int x = 0; x < img_sz.width; x+=10) 
    { 
     double dx = cvGetReal2D(velx, y, x);              // Gets X component of the flow 
     double dy = cvGetReal2D(vely, y, x);              // Gets Y component of the flow 

     CvPoint p = cvPoint(x, y); 

     double l = sqrt(dx*dx + dy*dy);                // This function sets a basic threshold for drawing on the image 
     if (l > 0) 
     { 
      double spinSize = 5.0 * l/l_max;              // Factor to normalise the size of the spin depeding on the length of the arrow 

      CvPoint p2 = cvPoint(p.x + (int)(dx), p.y + (int)(dy)); 
      cvLine(resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA); 

      double angle;                   // Draws the spin of the arrow 
      angle = atan2((double) p.y - p2.y, (double) p.x - p2.x); 

      p.x = (int) (p2.x + spinSize * cos(angle + 3.1416/4)); 
      p.y = (int) (p2.y + spinSize * sin(angle + 3.1416/4)); 
      cvLine(resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA, 0); 

      p.x = (int) (p2.x + spinSize * cos(angle - 3.1416/4)); 
      p.y = (int) (p2.y + spinSize * sin(angle - 3.1416/4)); 
      cvLine(resultDenseOpticalFlow, p, p2, CV_RGB(0,255,0), 1, CV_AA, 0); 

     } 
    } 
} 

Và đây là một ví dụ về cách mã OpenCV này sẽ trông như thế

enter image description here

Tôi hy vọng điều này giúp đỡ người khác Googling cho cùng một vấn đề.

+1

cảm ơn và hữu ích – wolvorinePk

+1

@wolvorinePk Tôi rất vui vì nó đã giúp ai đó! – Dan

+1

@Dan: Tôi có thể đề xuất bạn chỉnh sửa mã và có mã trong một hàm như "arrowedLine()" hay không. Trong đó có một cú pháp tương tự như cv :: line()? – mkuse

4

Các cvCalOpticalFlowLK không vectơ vận tốc âm mưu, nó tính các vectơ vận tốc. Nếu bạn không có các vectơ này, bạn phải gọi hàm này bằng hai hình ảnh. Tôi đoán bạn đã có những vectơ này, và bạn chỉ muốn vẽ chúng.

Trong trường hợp này, bạn có thể sử dụng cv::line function, ví dụ:

cv::line(yourImage, cv::Point(baseX, baseY), cv::Point(endX, endY)); 

Tôi hy vọng điều này sẽ giúp bạn!

+0

cảm ơn tôi đã thử dòng với nhiều cách khác nhau để tạo mũi tên bằng một hình ảnh, và bây giờ nó đã hoạt động. – wolvorinePk

+0

vì mục đích trợ giúp khác tôi đã thêm mã ở trên – wolvorinePk

+0

Vẽ các vectơ không có dấu (hướng/mũi tên) là thực hành không tốt. Tôi khuyên bạn nên trả lời dưới đây. – TimZaman

9

Dựa trên mã từ Dan và đề nghị của mkuse, đây là một chức năng với cú pháp tương tự như cv :: dòng():

static void arrowedLine(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, 
int thickness=1, int line_type=8, int shift=0, double tipLength=0.1) 
{ 
    const double tipSize = norm(pt1-pt2)*tipLength; // Factor to normalize the size of the tip depending on the length of the arrow 
    line(img, pt1, pt2, color, thickness, line_type, shift); 
    const double angle = atan2((double) pt1.y - pt2.y, (double) pt1.x - pt2.x); 
    Point p(cvRound(pt2.x + tipSize * cos(angle + CV_PI/4)), 
    cvRound(pt2.y + tipSize * sin(angle + CV_PI/4))); 
    line(img, p, pt2, color, thickness, line_type, shift); 
    p.x = cvRound(pt2.x + tipSize * cos(angle - CV_PI/4)); 
    p.y = cvRound(pt2.y + tipSize * sin(angle - CV_PI/4)); 
    line(img, p, pt2, color, thickness, line_type, shift); 
} 

Chúng ta sẽ thấy nếu những việc duy trì kho OpenCV sẽ thích it :-)

+2

Phiên bản OpenCV tiếp theo sẽ có [cv :: arrowedLine] (https://github.com/Itseez/opencv/blob/a7006ac21c2e41b98be5d6635d75b3962000986b/modules/core/doc/drawing_functions.rst#arrowedline) sẵn có – PhilLab

Các vấn đề liên quan