enter image description here我有一份文档的扫描件作为用户提交的图像,它仅覆盖纸张高度的40%。我只想裁剪那部分,如何实现。 不必总是将所需的表格放在纸的顶部,可以在任何地方,其余的是白纸,如何裁剪该部分?
我仅使用python制成的扫描仪获得的扫描副本,因此页面上几乎没有黑点。
答案 0 :(得分:0)
您可以考虑以下步骤来裁剪空白或不空白的部分:
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();
结果如下:
希望有帮助!
更新: 如果您对(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;
}
}
因此,一旦拥有这些点,便可以在图像的任何位置进行裁剪。