Как обрезать пустую часть изображения (форма документа) в Python? - PullRequest
0 голосов
/ 06 марта 2019

введите описание изображения здесь У меня есть отсканированная копия документа в виде изображения, отправленного пользователем, он покрывает только 40% высоты бумаги.Я хочу обрезать только ту часть, как этого добиться.Нет необходимости, чтобы требуемая форма всегда находилась сверху на бумаге, она может быть где угодно, а остальное - чистый белый лист, как обрезать эту часть?

Отсканированная копия, полученная мной с помощью сканерасделано только на python, поэтому на странице есть маленькие черные точки.

1 Ответ

0 голосов
/ 06 марта 2019

Вы можете рассмотреть шаги ниже, чтобы обрезать пустую или непустую часть:

cv::namedWindow("result", cv::WINDOW_FREERATIO);
cv::Mat img = cv::imread(R"(xbNQF.png)"); // read the image

// main code starts from here
cv::Mat gray; // convert the image to gray and put the result in gray mat
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); // img -> gray
// threshold the gray image to remove the noise and put the result again in gray image
// it will convert all the background to black and all the text and fields to white
cv::threshold(gray, gray, 150, 255, cv::THRESH_BINARY_INV);

// now enlage the text or the inpout text fields
cv::dilate(gray, gray, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 3)));
// now clean the image, remove unwanted small pixels
cv::erode(gray, gray, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)));

// find all non zero to get the max y
cv::Mat idx; // the findNonZero() function will put the result in this mat
cv::findNonZero(gray, idx); // pass the mat idx to the function
// now iterate throgh the idx to find the max y
double maxY = 0; // this will keep the max y, init value is 0
for (int i=0; i<idx.rows; ++i) {
    cv::Point pnt = idx.at<cv::Point>(i);
    if (pnt.y > maxY) { // if this Y is greater than the last Y, copy it to the last Y
        maxY = pnt.y; // this
    }
}

// crop the none blank (upper) part
// NOTE: from this point you can also crop the blank part
// (0,0) means start form left-top, (gray.cols, int(maxY+5)) means 
// whidth the same as the original image, and the height is
// the maxY + 5, 5 here means let give some margin the cropped image
// if you don't want, then you can delete it.
cv::Mat submat = img(cv::Rect(0, 0, gray.cols, int(maxY+5)));
cv::imshow("result", submat);

cv::waitKey();

И это результат:

enter image description here

Надеюсь, это поможет!

Обновление: Если вас интересуют все минимальные, максимальные значения (x, y), выполните поиск следующим образом:

double maxX = 0, minX = std::numeric_limits<double>::max();
double maxY = 0, minY = std::numeric_limits<double>::max();
for (int i=0; i<idx.rows; ++i) {
    cv::Point pnt = idx.at<cv::Point>(i);
    if (pnt.x > maxX) {
        maxX = pnt.x;
    }
    if (pnt.x < minX) {
        minX = pnt.x;
    }
    if (pnt.y > maxY) {
        maxY = pnt.y;
    }
    if (pnt.y < minY) {
        minY = pnt.y;
    }
}

Итак, вы можете обрезать любое место изображения, когда у вас есть эти точки.

...