Я задал похожий вопрос Вот но это больше ориентировано на тессеракт.
У меня есть образец изображения, как показано ниже. Я хотел бы сделать белый квадрат моей областью интересов, а затем обрезать эту часть (квадрат) и создать новое изображение с ним. Я буду работать с разными изображениями, чтобы квадрат не всегда находился в одном и том же месте на всех изображениях. Поэтому мне нужно будет как-то определить края квадрата.
Какие методы предварительной обработки я могу выполнить для достижения результата?
Используя ваше тестовое изображение, я смог удалить все шумы с помощью простого эрозия операция.
После этого, простая итерация на Mat
найти для угловых пикселей тривиально, и я говорил об этом на этот ответ. Для целей тестирования мы можем нарисовать зеленый линии между этими точками для отображения интересующей нас области в исходном изображении:
В конце я установить рентабельность инвестиций в исходное изображение и обрезать из этой части.
Окончательный результат отображается на изображении ниже:
Я написал пример кода, который выполняет эту задачу, используя Интерфейс C ++ OpenCV. Я уверен в ваших навыках по переводу этого кода на Python. Если вы не можете этого сделать, забудьте код и придерживайтесь дорожная карта Я поделился на этот ответ.
#include <cv.h>
#include <highgui.h>
int main(int argc, char* argv[])
{
cv::Mat img = cv::imread(argv[1]);
std::cout << "Original image size: " << img.size() << std::endl;
// Convert RGB Mat to GRAY
cv::Mat gray;
cv::cvtColor(img, gray, CV_BGR2GRAY);
std::cout << "Gray image size: " << gray.size() << std::endl;
// Erode image to remove unwanted noises
int erosion_size = 5;
cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS,
cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1),
cv::Point(erosion_size, erosion_size) );
cv::erode(gray, gray, element);
// Scan the image searching for points and store them in a vector
std::vector<cv::Point> points;
cv::Mat_<uchar>::iterator it = gray.begin<uchar>();
cv::Mat_<uchar>::iterator end = gray.end<uchar>();
for (; it != end; it++)
{
if (*it)
points.push_back(it.pos());
}
// From the points, figure out the size of the ROI
int left, right, top, bottom;
for (int i = 0; i < points.size(); i++)
{
if (i == 0) // initialize corner values
{
left = right = points[i].x;
top = bottom = points[i].y;
}
if (points[i].x < left)
left = points[i].x;
if (points[i].x > right)
right = points[i].x;
if (points[i].y < top)
top = points[i].y;
if (points[i].y > bottom)
bottom = points[i].y;
}
std::vector<cv::Point> box_points;
box_points.push_back(cv::Point(left, top));
box_points.push_back(cv::Point(left, bottom));
box_points.push_back(cv::Point(right, bottom));
box_points.push_back(cv::Point(right, top));
// Compute minimal bounding box for the ROI
// Note: for some unknown reason, width/height of the box are switched.
cv::RotatedRect box = cv::minAreaRect(cv::Mat(box_points));
std::cout << "box w:" << box.size.width << " h:" << box.size.height << std::endl;
// Draw bounding box in the original image (debugging purposes)
//cv::Point2f vertices[4];
//box.points(vertices);
//for (int i = 0; i < 4; ++i)
//{
// cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA);
//}
//cv::imshow("Original", img);
//cv::waitKey(0);
// Set the ROI to the area defined by the box
// Note: because the width/height of the box are switched,
// they were switched manually in the code below:
cv::Rect roi;
roi.x = box.center.x - (box.size.height / 2);
roi.y = box.center.y - (box.size.width / 2);
roi.width = box.size.height;
roi.height = box.size.width;
std::cout << "roi @ " << roi.x << "," << roi.y << " " << roi.width << "x" << roi.height << std::endl;
// Crop the original image to the defined ROI
cv::Mat crop = img(roi);
// Display cropped ROI
cv::imshow("Cropped ROI", crop);
cv::waitKey(0);
return 0;
}
Видя, что текст — это единственное большое пятно, а все остальное чуть больше пикселя, простого морфологического открытия должно хватить
Вы можете сделать это в opencv
или же с имиджмагией
После этого белый прямоугольник должен быть единственным, что осталось на изображении. Вы можете найти его с помощью opencvs findcontours, с помощью библиотеки CvBlobs для opencv или с помощью функции imagemagick -crop.
Вот ваше изображение с 2-мя ступенями эрозии и двумя ступенями расширения:
Вы можете просто вставить это изображение в функцию openCv findContours, как в Пример учебника квадратов получить должность