Определение угла перекоса на изображении с разбросанными символами

Я следил этот урок чтобы получить угол наклона изображения. Похоже, что 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);
}

ура

1

Решение

Я бы предложил сначала найти отдельные компоненты (например, строки и буквы), например, используя cv::threshold а также cv::findContours,

Затем вы можете отбросить отдельные узкие компоненты (то есть буквы). Вы можете сделать это используя cv::floodFill например. Это должно оставить вас только с линиями.

По сути, избавление от букв может обеспечить более легкий ввод для преобразования Хафа.

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

Затем используйте Hough Line Transform для контурного изображения.
С порогом накопителя 80 я получаю следующие линии, которые дают угол -3,81. Это высоко из-за выпадающей линии, которая является почти вертикальной. При таком подходе большинство линий будут иметь одинаковые значения углов, за исключением нескольких выбросов. Обнаружение и удаление выбросов даст вам лучшее приближение к углу.

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

введите описание изображения здесь

1

По вопросам рекламы [email protected]