2017-08-02 88 views
0

我的想法是画出所有通过计算Canny之前创建的垂直线,从交点到对角线到另一个交点(此点来自一个交点之间的交点)弧形和对角线)。这里作为参考图像,红色垂直(哈夫)线应drawen: enter image description here将垂直HoughLines画到某个交点

直到但我刚刚发现这个实现所有垂直线:

int main(int argc, char *argv[]) { 
    std::vector<cv::Point> diagonalLine = DiagonalLines::diagonalLines(src); 

    Mat wdst, cwdst, contRegion; 
    vector<Vec4i> vericalLines; 
    double maxLineGap = 200.0; 
    double threshold = 100; 

    std::vector<cv::Vec4i> elemLinesCur;            

    cv::Scalar mu, sigma; 
    meanStdDev(src, mu, sigma); 

    Canny(src, wdst, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0], 3, false); 
    cvtColor(wdst, cwdst, CV_GRAY2BGR); 

    HoughLinesP(wdst, vericalLines, 1, CV_PI/2, threshold, 50, 200); 

    cv::Vec4i current, previous; 
    cv::Point pt1, pt2, ppt1, ppt2; 

    for (size_t i = 1; i < vericalLines.size(); i++) { 
    current = vericalLines[i]; 
    pt1 = cv::Point(current[0], current[1]); 
    pt2 = cv::Point(current[2], current[3]); 

    previous = vericalLines[i - 1]; 
    ppt1 = cv::Point(previous[0], previous[1]); 
    ppt2 = cv::Point(previous[2], previous[3]); 

    if (diagonalLine[i - 1].y > pt2.y && diagonalLine[i].y < pt1.y) { 
     std::cout << "Intersection: " << pt2.x << "\n"; 
    } 

    double distanceBetweenPointsX = abs(pt1.x - ppt1.x)*sqrt(2); 

    if (distanceBetweenPointsX >= 12) { 
     elemLinesCur.push_back(current); 

     double angle = atan2(ppt2.y - ppt1.y, ppt2.x - ppt1.x) * 180.0/CV_PI;  ///draw only vertical lines (90 degree) 
     if (angle) { 
      line(cwdst, pt1, pt2, cv::Scalar(0, 0, 255), 2, CV_AA); 
     } 
//do some stuff 
} 

...这里的方法,其中只检测对角线(它看起来类同上面一个):

std::vector<cv::Point> diagonalLines(cv::Mat src) { 
std::vector<cv::Point> hitPoint; 

Scalar mu, sigma; 
meanStdDev(src, mu, sigma); 

Canny(src, ddst, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0], 3, false); 

cvtColor(ddst, cddst, CV_GRAY2BGR); 
HoughLinesP(ddst, vertlines, 1, CV_PI/180, 100, 50, 10); 

cv::Point pt1, pt2; 
for (size_t i = 1; i < vertlines.size(); i++) { 
    cv::Vec4i current = vertlines[i]; 
    pt1 = cv::Point(current[0], current[1]); 
    pt2 = cv::Point(current[2], current[3]); 

    double angle = atan2(pt2.y - pt1.y, pt2.x - pt1.x) * 180.0/CV_PI; 
    if (angle != -90 && angle != 90) { 
     //line(cddst, pt1, pt2, Scalar(0, 0, 255), 2, CV_AA); 
     hitPoint.push_back(pt1); 
     hitPoint.push_back(pt2); 
    } 
} 
return hitPoint; 
} 

我所知道的: 我应该计算所有这些intersecti在点上,是的,我也试过if (diagonalLine[i - 1].y > pt2.y && diagonalLine[i].y < pt1.y),但我没有得到进一步的步骤。有人能帮助我吗?先谢谢你!

回答

0

OpenCV函数line()接受端点作为参数,所以您只需计算交点并将这些交点用于垂直线的端点。您可以直接从作为HoughLinesP()using determinants的结果的端点计算交叉点。

在Python,从而计算交会点的函数可能看起来像

def find_intersection(line1, line2): 
    # extract points 
    x1, y1 = line1[0] 
    x2, y2 = line1[1] 
    x3, y3 = line2[0] 
    x4, y4 = line2[1] 
    # compute determinant 
    Px = ((x1*y2 - y1*x2)*(x3-x4) - (x1-x2)*(x3*y4 - y3*x4))/
     ((x1-x2)*(y3-y4) - (y1-y2)*(x3-x4)) 
    Py = ((x1*y2 - y1*x2)*(y3-y4) - (y1-y2)*(x3*y4 - y3*x4))/
     ((x1-x2)*(y3-y4) - (y1-y2)*(x3-x4)) 
    return (int(Px), int(Py)) 

让我们展示如何使用这个。假设你的形象是这样的:

# draw image and lines 
img = np.ones((500, 500, 3)) * 255 
diag1 = [(0, 0), (499, 100)] 
diag2 = [(0, 499), (499, 399)] 
vert1 = [(100, 0), (100, 499)] 
vert2 = [(400, 0), (400, 499)] 
cv2.line(img, diag1[0], diag1[1], color=[0, 0, 255]) 
cv2.line(img, diag2[0], diag2[1], color=[0, 0, 255]) 
cv2.line(img, vert1[0], vert1[1], color=[0, 255, 0]) 
cv2.line(img, vert2[0], vert2[1], color=[0, 255, 0]) 

Full lines drawn

要切断他们在路口,只需使用功能找到这些点,只有每个对角线画在交叉点处的垂直线。

# get intersection points 
vert1_intersect = [find_intersection(diag1, vert1), find_intersection(diag2, vert1)] 
vert2_intersect = [find_intersection(diag1, vert2), find_intersection(diag2, vert2)] 

# draw vertical lines from intersection points 
img = np.ones((500, 500, 3)) * 255 
diag1 = [(0, 0), (499, 100)] 
diag2 = [(0, 499), (499, 399)] 
vert1 = [(100, 0), (100, 499)] 
vert2 = [(400, 0), (400, 499)] 
cv2.line(img, diag1[0], diag1[1], color=[0, 0, 255]) 
cv2.line(img, diag2[0], diag2[1], color=[0, 0, 255]) 
cv2.line(img, vert1_intersect[0], vert1_intersect[1], color=[0, 255, 0]) 
cv2.line(img, vert2_intersect[0], vert2_intersect[1], color=[0, 255, 0]) 

Vertical lines stopping at intersection point

+0

'line1'和'line2'应该是2x4的点,对不对?因为我实际上正在使用C++,现在我试图实现你的方法.. – Viktoria

+0

我在第三部分'在我的C++代码中获取交叉点'失败。 :/因为我的方法'std :: vector diagonalline'返回一个向量 – Viktoria

+0

@Viktoria没关系,你可以只取任意两点就行!我可能会将矢量中的第一个和最后一个点作为对角线的“端点”。该公式适用于任何点,但它们不一定是端点。在我的代码中,也许只是忽略我如何存储每一行​​。如果你喜欢,你可以将它们存储在标准格式的C++向量中。正如你在函数中看到的那样,重要的部分就是使用来自每行的两对点。对1可以是'(x1,y1),(x2,y2)',并且对2可以是'(x3,y3),(x4,y4)'。 –