2012-10-31 35 views
5

Vâng câu hỏi nói lên tất cả,Làm thế nào để vẽ đường thẳng không xếp hàng phân khúc OpenCV 2.4.2

Tôi biết các chức năng Line(), thu hút đoạn thẳng giữa hai điểm.

Tôi cần vẽ đường kẻ NOT một đoạn đường, cũng sử dụng hai điểm của đoạn đường.


[EN: Chỉnh sửa từ gì trước đây đã được đăng như một câu trả lời cho câu hỏi]

tôi đã sử dụng giải pháp của bạn và nó thực hiện được kết quả tốt trong các đường ngang, nhưng tôi vẫn còn có vấn đề trong đường dọc .

Ví dụ: sau ví dụ sử dụng các điểm [306,411] và [304,8] (màu tím) và đường vẽ (màu đỏ), trên hình ảnh có 600x600 pixel. Bạn có mẹo nào không?

enter image description here

Trả lời

6

Bạn sẽ cần phải viết một chức năng để làm điều đó cho chính mình. Tôi đề nghị bạn đặt dòng của bạn trong ax + by + c = 0 hình thức và sau đó cắt nó với 4 cạnh của hình ảnh của bạn. Hãy nhớ rằng nếu bạn có một dòng trong biểu mẫu [a b c], việc tìm giao lộ của nó với một dòng khác đơn giản là sản phẩm chéo của cả hai. Các cạnh của hình ảnh của bạn sẽ là

top_horizontal = [0 1 0]; 
left_vertical = [1 0 0]; 
bottom_horizontal = [0 1 -image.rows]; 
right_vertical = [1 0 -image.cols]; 

Ngoài ra, nếu bạn biết một điểm nào đó về khoảng cách giữa các điểm, bạn cũng không thể chỉ ra các điểm Line() cần phải có trên hình ảnh.

5

Tôi thấy đây là câu hỏi khá cũ. Tôi đã có chính xác cùng một vấn đề và tôi đã sử dụng mã đơn giản này:

double Slope(int x0, int y0, int x1, int y1){ 
    return (double)(y1-y0)/(x1-x0); 
} 

void fullLine(cv::Mat *img, cv::Point a, cv::Point b, cv::Scalar color){ 
    double slope = Slope(a.x, a.y, b.x, b.y); 

    Point p(0,0), q(img->cols,img->rows); 

    p.y = -(a.x - p.x) * slope + a.y; 
    q.y = -(b.x - q.x) * slope + b.y; 

    line(*img,p,q,color,1,8,0); 
} 

Trước tiên tôi tính toán độ dốc của đoạn đường và sau đó tôi "mở rộng" đoạn đường vào đường viền của hình ảnh. Tôi tính toán các điểm mới của dòng nằm trong x = 0 và x = image.width. Điểm chính nó có thể được bên ngoài hình ảnh, mà là một loại lừa khó chịu, nhưng giải pháp là rất đơn giản.

+1

Đây là câu trả lời đúng cho openCV. Câu trả lời được chọn là rác. Tôi đã sao chép và dán nó và nó hoạt động. Cảm ơn rất nhiều. –

+1

Sẽ bị lỗi nếu x1-x0 = 0. –

1

Câu trả lời này được chia thành hai phần từ câu trả lời của pajus_cz nhưng được cải thiện một chút.

Chúng tôi có hai điểm và chúng tôi cần lấy phương trình đường y = mx + b để có thể vẽ đường thẳng.

Có hai biến chúng ta cần phải nhận được

1- Slope (m)

Slope equation

2- b mà có thể được lấy thông qua các phương trình dòng sử dụng bất kỳ điểm nào từ hai chúng tôi đã có sau khi tính toán độ dốc .

void drawStraightLine(cv::Mat *img, cv::Point2f p1, cv::Point2f p2, cv::Scalar color) 
{ 
     Point2f p, q; 
     // Check if the line is a vertical line because vertical lines don't have slope 
     if (p1.x != p2.x) 
     { 
       p.x = 0; 
       q.x = img->cols; 
       // Slope equation (y1 - y2)/(x1 - x2) 
       float m = (p1.y - p2.y)/(p1.x - p2.x); 
       // Line equation: y = mx + b 
       float b = p1.y - (m * p1.x); 
       p.y = m * p.x + b; 
       q.y = m * q.x + b; 
     } 
     else 
     { 
       p.x = q.x = p2.x; 
       p.y = 0; 
       q.y = img->rows; 
     } 

     cv::line(*img, p, q, color, 1); 
} 
3

tôi đã cùng một vấn đề và phát hiện ra rằng có nó là một known bug về 2.4.x OpenCV, cố định đã cho các phiên bản mới hơn.

Đối với các phiên bản 2.4.x, giải pháp là để cắt dòng trước khi cốt truyện nó bằng cách sử cv::clipLine()

Ở đây có một chức năng tôi đã tự nhủ rằng hoạt động tốt trên 2.4.13 OpenCV

void Detector::drawFullImageLine(cv::Mat& img, const std::pair<cv::Point, cv::Point>& points, cv::Scalar color) 
{ 
    //points of line segment 
    cv::Point p1 = points.first; 
    cv::Point p2 = points.second; 

    //points of line segment which extend the segment P1-P2 to 
    //the image borders. 
    cv::Point p,q; 

    //test if line is vertical, otherwise computes line equation 
    //y = ax + b 
    if (p2.x == p1.x) 
    { 
     p = cv::Point(p1.x, 0); 
     q = cv::Point(p1.x, img.rows); 
    } 
    else 
    { 
     double a = (double)(p2.y - p1.y)/(double) (p2.x - p1.x); 
     double b = p1.y - a*p1.x; 

     p = cv::Point(0, b); 
     q = cv::Point(img.rows, a*img.rows + b); 

     //clipline to the image borders. It prevents a known bug on OpenCV 
     //versions 2.4.X when drawing 
     cv::clipLine(cv::Size(img.rows, img.cols), p, q); 
    } 

    cv::line(img, p, q, color, 2); 
} 
+0

'cv :: clipLine()' là giải pháp đúng cho OpenCV. Điều này nên được chấp nhận câu trả lời. Cảm ơn rất nhiều – Arxeiss

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