【问题标题】:Draw vertical HoughLines till certain intersection points绘制垂直霍夫线直到某些交点
【发布时间】:2017-08-03 07:36:08
【问题描述】:

我的想法是绘制所有垂直线,这些垂直线是通过之前计算 Canny 创建的,从交叉点到对角线再到另一个交叉点(这个点也来自垂直线和对角线之间的交叉点)。作为此处的参考图像,应绘制红色垂直(霍夫)线:

直到我用这个实现检测到所有垂直线:

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;
}

我所知道的: 我应该计算所有这些交点,是的,我也在if (diagonalLine[i - 1].y &gt; pt2.y &amp;&amp; diagonalLine[i].y &lt; pt1.y) 中尝试过,但我没有得到进一步的步骤。有人可以帮我吗?提前谢谢!

【问题讨论】:

    标签: c++ opencv hough-transform


    【解决方案1】:

    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])
    

    要在交点处将它们切断,只需使用该函数找到这些点,然后只在与每条对角线的交点处绘制垂直线。

    # 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])
    

    【讨论】:

    • line1line2 应该是 2x4 点,对吧?因为我实际上正在使用 C++,现在我正在尝试实现您的方法..
    • 我的 C++ 代码的第三部分 get intersection points 失败了。 :/ 因为我的方法std::vector&lt;cv::Point&gt; diagonalLines 返回一个向量
    • @Viktoria 没关系,你可以取任意两点就行了!我可能只是将向量中的第一个和最后一个点作为对角线的“端点”。该公式适用于线上的任何点,但它们不必是端点。在我的代码中,也许只是忽略我如何存储每一行​​。如果您愿意,您可以将它们存储在点格式的普通 C++ 向量中。正如您在函数中看到的那样,重要的部分只是使用每条线上的两对点。 Pair 1 可以是(x1, y1), (x2, y2),Pair 2 可以是(x3, y3), (x4, y4)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-17
    • 2014-06-09
    • 1970-01-01
    • 1970-01-01
    • 2018-05-24
    • 2015-07-27
    • 1970-01-01
    相关资源
    最近更新 更多