【问题标题】:Skew angle detection on a image with scattered characters对具有分散字符的图像进行倾斜角度检测
【发布时间】:2015-02-15 10:39:21
【问题描述】:

我一直在关注this tutorial 以获取图像的倾斜角度。当字符在目标图像上有点分散时,HoughLinesP 似乎正在努力寻找线条。

这是我的输入图像:

这是 HoughLinesP 找到的线条:

它并没有真正得到大部分的台词,而且对我来说原因似乎很明显。这是因为我将 minLineWidth 设置为 (size.width / 2.f)。关键是,由于它发现的几条线,结果证明倾斜角度也是错误的。 (在这种情况下为-3.15825,它应该接近 0.5)

我试图侵蚀我的输入文件以使字符更接近,在这种情况下它似乎可以解决,但我认为这不是类似情况的最佳方法。

这是我侵蚀的输入图像:

这是 HoughLinesP 找到的线条:

这次它发现了 -0.2185 度的倾斜角,这是我所期待的,但另一方面它正在失去线条之间的垂直空间,在我看来这不是一件好事。

是否有其他方法可以对这种图像进行预处理,以使 houghLinesP 对分散的字符有更好的效果?

这是我正在使用的源代码:

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;


static cv::Scalar randomColor( cv::RNG& rng )
{
  int icolor = (unsigned) rng;
  return cv::Scalar( icolor&255, (icolor>>8)&255, (icolor>>16)&255 );
}

void rotate(cv::Mat& src, double angle, cv::Mat& dst)
{
    int len = std::max(src.cols, src.rows);
    cv::Point2f pt(len/2., len/2.);
    cv::Mat r = cv::getRotationMatrix2D(pt, angle, 1.0);

    cv::warpAffine(src, dst, r, cv::Size(len, len));
}

double compute_skew(cv::Mat& src)
{
    // Random number generator
    cv::RNG rng( 0xFFFFFFFF );

    cv::Size size = src.size();
    cv::bitwise_not(src, src);
    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(src, lines, 1, CV_PI/180, 100, size.width / 2.f, 20);
    cv::Mat disp_lines(size, CV_8UC3, cv::Scalar(0, 0, 0));
    double angle = 0.;
    unsigned nb_lines = lines.size();
    for (unsigned i = 0; i < nb_lines; ++i)
    {
        cv::line(disp_lines, cv::Point(lines[i][0], lines[i][1]),
                 cv::Point(lines[i][2], lines[i][3]), randomColor(rng));
        angle += atan2((double)lines[i][3] - lines[i][1],
                       (double)lines[i][2] - lines[i][0]);
    }
    angle /= nb_lines; // mean angle, in radians.

    std::cout << angle * 180 / CV_PI << std::endl;

    cv::imshow("HoughLinesP", disp_lines);
    cv::waitKey(0);

    return angle * 180 / CV_PI;
}
int main()
{
    // Load in grayscale.
    cv::Mat img = cv::imread("IMG_TESTE.jpg", 0);
    cv::Mat rotated;
    double angle = compute_skew(img);
    rotate(img, angle, rotated);
    //Show image
    cv::imshow("Rotated", rotated);
    cv::waitKey(0);
}

干杯

【问题讨论】:

  • HoughLinesP 需要白色(或非零)像素作为前景,你的字符和线条是黑色的。
  • 嗨 Micka,在我使用 HoughLinesP 之前,图像正在被反转。它也在我提供的源代码中。
  • 这是用于反转图像的代码:cv::bitwise_not(src, src);
  • 抱歉,根本没看你的代码。只看到您被侵蚀的“输入图像”并假设它用于 HoughLinesP ;)

标签: c++ image opencv image-processing skew


【解决方案1】:

我建议首先找到单个组件(即线条和字母),例如使用 cv::thresholdcv::findContours

然后,您可以删除窄的单个组件(即字母)。例如,您可以使用 cv::floodFill 来执行此操作。这应该只留下线条。

实际上,去掉字母可能会为 Hough 变换提供更容易的输入。

【讨论】:

    【解决方案2】:

    尝试将字符组检测为块,然后找到这些块的轮廓。下面我使用模糊、形态学开场和阈值操作来完成。

    Mat im = imread("yCK4t.jpg", 0);
    Mat blurred;
    GaussianBlur(im, blurred, Size(5, 5), 2, 2);
    Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
    Mat morph;
    morphologyEx(blurred, morph, CV_MOP_OPEN, kernel);
    Mat bw;
    threshold(morph, bw, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
    Mat cont = Mat::zeros(im.rows, im.cols, CV_8U);
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    findContours(bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
    for(int idx = 0; idx >= 0; idx = hierarchy[idx][0])
    {
        drawContours(cont, contours, idx, Scalar(255, 255, 255), 1);
    }
    

    然后在轮廓图像上使用霍夫线变换。 使用累加器阈值 80,我得到以下线,导致角度为 -3.81。这是因为离群值线几乎是垂直的。使用这种方法,除了少数异常值外,大多数线将具有相似的角度值。检测并丢弃异常值将为您提供更好的角度近似值。

    HoughLinesP(cont, lines, 1, CV_PI/180, 80, size.width / 4.0f, size.width / 8.0f);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 2016-03-29
      • 2016-02-03
      • 2020-04-18
      相关资源
      最近更新 更多