2024-01-24 04:05:05 +00:00
|
|
|
#include "auto_crop.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <huagao/hgscanner_error.h>
|
|
|
|
#include <sane/sane_ex.h>
|
|
|
|
#include <cis/cis_param.h>
|
|
|
|
#include <opencv2/imgproc/hal/hal.hpp>
|
|
|
|
#include "ImageProcess_Public.h"
|
|
|
|
|
|
|
|
|
|
|
|
#define FRONT_TOP 70
|
|
|
|
#define FX_FY 0.5f
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
static std::string device_opt_json[] = {
|
2024-02-29 07:45:50 +00:00
|
|
|
"{\"crop\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u88c1\\u5207\",\"desc\":\"\\u6309\\u56fe\\u7247\\u5927\\u5c0f\\u88c1\\u5207\",\"type\":\"bool\",\"pos\":30,\"ui-pos\":-1,\"auth\":0,\"size\":4,\"cur\":true,\"default\":true,\"depend\":\"page!=\\u5bf9\\u6298\"},\"is-anti-skew\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u81ea\\u52a8\\u7ea0\\u504f\",\"desc\":\"\\u81ea\\u52a8\\u7ea0\\u6b63\\u6b6a\\u659c\\u9001\\u5165\\u7684\\u6587\\u7a3f\\u56fe\\u50cf\",\"type\":\"bool\",\"pos\":33,\"fix-id\":34844,\"ui-pos\":-1,\"auth\":0,\"size\":4,\"cur\":true,\"default\":true,\"depend\":\"page!=\\u5bf9\\u6298\"},\"is-erase-black-frame\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u6d88\\u9664\\u9ed1\\u6846\",\"desc\":\"\\u6d88\\u9664\\u6587\\u7a3f\\u8303\\u56f4\\u5916\\u7684\\u9ed1\\u8272\\u80cc\\u666f\",\"type\":\"bool\",\"pos\":35,\"fix-id\":34849,\"ui-pos\":-1,\"auth\":0,\"size\":4,\"cur\":true,\"default\":true},\"bkg-fill-mode\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u80cc\\u666f\\u586b\\u5145\\u65b9\\u5f0f\",\"desc\":\"\\u9009\\u62e9\\u80cc\\u666f\\u586b\\u5145\\u65b9\\u5f0f\",\"type\":\"string\",\"pos\":36,\"fix-id\":34854,\"ui-pos\":-1,\"auth\":0,\"size\":16,\"cur\":\"\\u51f8\\u591a\\u8fb9\\u5f62\",\"default\":\"\\u51f8\\u591a\\u8fb9\\u5f62\",\"range\":[\"\\u51f8\\u591a\\u8fb9\\u5f62\",\"\\u51f9\\u591a\\u8fb9\\u5f62\"],\"depend\":\"is-erase-black-frame==true\"},\"threshold\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u9608\\u503c\",\"desc\":\"\\u6587\\u7a3f\\u5e95\\u8272\\u4e0e\\u9ed1\\u8272\\u80cc\\u666f\\u7070\\u5ea6\\u503c\\u7684\\u5dee\\u503c\\u5927\\u4e8e\\u8be5\\u503c\\uff0c\\u624d\\u4f1a\\u88ab\\u8bc6\\u522b\\u4e3a\\u6587\\u7a3f\",\"type\":\"int\",\"pos\":37,\"fix-id\":34851,\"ui-pos\":-1,\"auth\":0,\"size\":4,\"cur\":40,\"default\":40,\"range\":{\"min\":30,\"max\":50,\"step\":1},\"depend\":\"is-erase-black-frame==true||paper==\\u5339\\u914d\\u539f\\u59cb\\u5c3a\\u5bf8||paper==\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8||paper==\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8\\u81ea\\u52a8\\u88c1\\u5207||is-anti-skew==true\"},\"anti-noise-level\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u80cc\\u666f\\u6297\\u566a\\u7b49\\u7ea7\",\"desc\":\"\\u80fd\\u591f\\u5bb9\\u5fcd\\u7684\\u80cc\\u666f\\u6742\\u8272\\u6761\\u7eb9\\u7684\\u5bbd\\u5ea6\",\"type\":\"int\",\"pos\":38,\"fix-id\":34852,\"ui-pos\":-1,\"auth\":0,\"size\":4,\"cur\":8,\"default\":8,\"range\":{\"min\":2,\"max\":20,\"step\":1},\"depend\":\"is-erase-black-frame==true||paper==\\u5339\\u914d\\u539f\\u59cb\\u5c3a\\u5bf8||paper==\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8||paper==\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8\\u81ea\\u52a8\\u88c1\\u5207||is-anti-skew==true\"},\"margin\":{\"cat\":\"imgp\",\"group\":\"imgp\",\"title\":\"\\u8fb9\\u7f18\\u7f29\\u8fdb\",\"desc\":\"\\u5bfb\\u627e\\u6587\\u7a3f\\u8fb9\\u7f18\\u65f6\\u5bf9\\u8fb9\\u7f18\\u7684\\u4fb5\\u5165\\u7a0b\\u5ea6\",\"type\":\"int\",\"pos\":40,\"fix-id\":34853,\"ui-pos\":-1,\"auth\":0,\"size\":4,\"cur\":5,\"default\":5,\"range\":{\"min\":2,\"max\":30,\"step\":1},\"depend\":\"is-erase-black-frame==true||paper==\\u5339\\u914d\\u539f\\u59cb\\u5c3a\\u5bf8||paper==\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8||paper==\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8\\u81ea\\u52a8\\u88c1\\u5207||is-anti-skew==true\"},\"paper\":{\"cat\":\"base\",\"group\":\"base\",\"title\":\"\\u7eb8\\u5f20\\u5c3a\\u5bf8\",\"desc\":\"\\u8bbe\\u7f6e\\u51fa\\u56fe\\u5927\\u5c0f\",\"type\":\"string\",\"pos\":1000,\"fix-id\":34831,\"ui-pos\":-1,\"auth\":0,\"size\":44,\"cur\":\"\\u5339\\u914d\\u539f\\u59cb\\u5c3a\\u5bf8\",\"default\":\"\\u5339\\u914d\\u539f\\u59cb\\u5c3a\\u5bf8\",\"range\":[\"A3\",\"8\\u5f00\",\"A4\",\"16\\u5f00\",\"A5\",\"A6\",\"B4\",\"B5\",\"B6\",\"Letter\",\"Double Letter\",\"LEGAL\",\"\\u5339\\u914d\\u539f\\u59cb\\u5c3a\\u5bf8\",{\"resolution<500\":\"\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8\\u81ea\\u52a8\\u88c1\\u5207\"},{\"resolution<500\":\"\\u6700\\u5927\\u626b\\u63cf\\u5c3a\\u5bf8\"},{\"resolution<500\":\"\\u4e09\\u8054\\u8bd5\\u5377\"}]},\"lateral\":{\"cat\":\"base\",\"
|
2024-01-24 04:05:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static void myWarpAffine(cv::InputArray _src, cv::OutputArray _dst, cv::InputArray _M0, cv::Size dsize, int flags, int borderType, const cv::Scalar& borderValue)
|
|
|
|
{
|
|
|
|
int interpolation = flags;
|
|
|
|
cv::Mat src = _src.getMat(), M0 = _M0.getMat();
|
|
|
|
cv::Mat dst = _dst.getMat();
|
|
|
|
|
|
|
|
if (dst.data == src.data)
|
|
|
|
src = src.clone();
|
|
|
|
|
|
|
|
double M[6] = { 0 };
|
|
|
|
cv::Mat matM(2, 3, CV_64F, M);
|
|
|
|
if (interpolation == cv::INTER_AREA)
|
|
|
|
interpolation = cv::INTER_LINEAR;
|
|
|
|
|
|
|
|
M0.convertTo(matM, matM.type());
|
|
|
|
|
|
|
|
if (!(flags & cv::WARP_INVERSE_MAP))
|
|
|
|
{
|
|
|
|
double D = M[0] * M[4] - M[1] * M[3];
|
|
|
|
D = D != 0 ? 1. / D : 0;
|
|
|
|
double A11 = M[4] * D, A22 = M[0] * D;
|
|
|
|
M[0] = A11; M[1] *= -D;
|
|
|
|
M[3] *= -D; M[4] = A22;
|
|
|
|
double b1 = -M[0] * M[2] - M[1] * M[5];
|
|
|
|
double b2 = -M[3] * M[2] - M[4] * M[5];
|
|
|
|
M[2] = b1; M[5] = b2;
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::hal::warpAffine(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows,
|
|
|
|
M, interpolation, borderType, borderValue.val);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
#define OPTION_FUNC(name) auto name = [this](void* val) -> void
|
|
|
|
|
|
|
|
auto_crop::auto_crop() : image_processor("auto_crop")
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
|
|
|
|
ADD_THIS_JSON();
|
|
|
|
}
|
|
|
|
auto_crop::~auto_crop()
|
|
|
|
{}
|
|
|
|
|
|
|
|
void auto_crop::init(void)
|
|
|
|
{
|
2024-02-29 07:45:50 +00:00
|
|
|
OPTION_FUNC(crop)
|
|
|
|
{
|
|
|
|
enabled_ = *(bool*)val;
|
|
|
|
};
|
2024-01-24 04:05:05 +00:00
|
|
|
OPTION_FUNC(deskew)
|
|
|
|
{
|
2024-02-29 07:45:50 +00:00
|
|
|
deskew_ = *(bool*)val;
|
2024-01-24 04:05:05 +00:00
|
|
|
};
|
|
|
|
OPTION_FUNC(bg)
|
|
|
|
{
|
|
|
|
fill_bg_ = *(bool*)val;
|
|
|
|
};
|
|
|
|
OPTION_FUNC(bgm)
|
|
|
|
{
|
|
|
|
convex_ = strcmp((char*)val, WORDS_FILLBG_CONVEX) == 0;
|
|
|
|
};
|
|
|
|
OPTION_FUNC(thr)
|
|
|
|
{
|
|
|
|
threshold_ = *(int*)val;
|
|
|
|
};
|
|
|
|
OPTION_FUNC(noise)
|
|
|
|
{
|
|
|
|
noise_ = *(int*)val;
|
|
|
|
};
|
|
|
|
OPTION_FUNC(margin)
|
|
|
|
{
|
|
|
|
indent_ = *(int*)val;
|
|
|
|
};
|
|
|
|
OPTION_FUNC(paper)
|
|
|
|
{
|
2024-02-25 01:54:19 +00:00
|
|
|
crop_ = strcmp((char*)val, WORDS_PAPER_ORIGIN_SIZE) == 0 ||
|
2024-01-24 09:40:41 +00:00
|
|
|
strcmp((char*)val, WORDS_PAPER_MAX_SIZE_CROP) == 0;
|
2024-01-24 04:05:05 +00:00
|
|
|
if(crop_)
|
|
|
|
memset(&fixed_paper_, 0, sizeof(fixed_paper_));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fixed_paper_ = paper::size((char*)val);
|
|
|
|
if(lateral_)
|
|
|
|
paper::swap_size(fixed_paper_);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
OPTION_FUNC(lat)
|
|
|
|
{
|
|
|
|
if(lateral_ != *(bool*)val)
|
|
|
|
paper::swap_size(fixed_paper_);
|
|
|
|
lateral_ = *(bool*)val;
|
|
|
|
};
|
|
|
|
|
2024-02-29 07:45:50 +00:00
|
|
|
opt_handler_[SANE_OPT_NAME(CROP)] = crop;
|
2024-01-31 01:41:22 +00:00
|
|
|
opt_handler_[SANE_OPT_NAME(ANTI_SKEW)] = deskew;
|
|
|
|
opt_handler_[SANE_OPT_NAME(ERASE_BLACK_FRAME)] = bg;
|
|
|
|
opt_handler_[SANE_OPT_NAME(FILL_BKG_MODE)] = bgm;
|
|
|
|
opt_handler_[SANE_OPT_NAME(THRESHOLD)] = thr;
|
|
|
|
opt_handler_[SANE_OPT_NAME(ANTI_NOISE_LEVEL)] = noise;
|
|
|
|
opt_handler_[SANE_OPT_NAME(MARGIN)] = margin;
|
|
|
|
opt_handler_[SANE_OPT_NAME(PAPER)] = paper;
|
|
|
|
opt_handler_[SANE_OPT_NAME(LATERAL)] = lat;
|
2024-01-24 04:05:05 +00:00
|
|
|
}
|
|
|
|
int auto_crop::work(PROCIMGINFO& in, PROCIMGINFO& out)
|
|
|
|
{
|
|
|
|
int ret = SCANNER_ERR_OK,
|
2024-01-24 09:40:41 +00:00
|
|
|
dWidth = fixed_paper_.cx * 1.0f / MM_PER_INCH * in.info.resolution_x + .5f,
|
|
|
|
dHeight = fixed_paper_.cy * 1.0f / MM_PER_INCH * in.info.resolution_x + .5f;
|
2024-01-24 04:05:05 +00:00
|
|
|
|
2024-02-25 01:54:19 +00:00
|
|
|
cv::Mat thre, resize;
|
2024-01-24 04:05:05 +00:00
|
|
|
|
2024-02-25 01:54:19 +00:00
|
|
|
cv::resize(in.img, resize, cv::Size(), FX_FY, FX_FY, cv::INTER_NEAREST);
|
|
|
|
hg::threshold_Mat(resize, thre, threshold_);
|
2024-01-24 04:05:05 +00:00
|
|
|
|
|
|
|
if (noise_ > 0)
|
|
|
|
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, getStructuringElement(cv::MORPH_RECT, cv::Size(cv::max(static_cast<int>(noise_ * FX_FY), 1), 1)),
|
|
|
|
cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
|
|
|
|
|
|
|
|
std::vector<cv::Vec4i> hierarchy;
|
|
|
|
std::vector<std::vector<cv::Point>> contours;
|
|
|
|
|
|
|
|
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
|
|
|
|
|
|
|
|
for (std::vector<cv::Point>& sub : contours)
|
|
|
|
for (cv::Point& p : sub)
|
|
|
|
p /= FX_FY;
|
|
|
|
|
|
|
|
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
|
|
|
|
|
|
|
|
if (maxContour.empty())
|
|
|
|
{
|
|
|
|
if (crop_)
|
|
|
|
out.img = in.img.clone();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cv::Rect roi = cv::Rect((in.img.cols - dWidth) / 2, FRONT_TOP, dWidth, dHeight) & cv::Rect(0, 0, in.img.cols, in.img.rows);
|
|
|
|
out.img = in.img(roi).clone();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::RotatedRect rect = hg::getBoundingRect(maxContour);
|
2024-02-25 01:54:19 +00:00
|
|
|
|
2024-01-24 04:05:05 +00:00
|
|
|
if (rect.size.width < 1 || rect.size.height < 1)
|
|
|
|
{
|
|
|
|
out.img = in.img;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::Scalar blankColor;
|
|
|
|
if (fill_bg_)
|
2024-01-24 09:40:41 +00:00
|
|
|
if (/*isColorBlank*/0)
|
2024-01-24 04:05:05 +00:00
|
|
|
{
|
|
|
|
cv::Rect boudingRect = cv::boundingRect(maxContour);
|
|
|
|
boudingRect.x *= FX_FY;
|
|
|
|
boudingRect.y *= FX_FY;
|
|
|
|
boudingRect.width *= FX_FY;
|
|
|
|
boudingRect.height *= FX_FY;
|
|
|
|
|
|
|
|
cv::Mat temp_bgc;
|
|
|
|
cv::resize(in.img(boudingRect), temp_bgc, cv::Size(200, 200));
|
|
|
|
blankColor = hg::getBackGroundColor(temp_bgc, cv::Mat(), 10);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
blankColor = cv::Scalar::all(255);
|
|
|
|
else
|
|
|
|
blankColor = cv::Scalar::all(0);
|
|
|
|
|
|
|
|
if (crop_)
|
|
|
|
if (deskew_)
|
|
|
|
out.img = cv::Mat(cv::Size(rect.size), in.img.type(), blankColor);
|
|
|
|
else
|
|
|
|
out.img = cv::Mat(/*rect.boundingRect().size()*/ cv::boundingRect(maxContour).size(), in.img.type(), blankColor);
|
|
|
|
else
|
|
|
|
out.img = cv::Mat(dHeight, dWidth, in.img.type(), blankColor);
|
|
|
|
|
|
|
|
cv::Mat dstROI;
|
|
|
|
if (deskew_ && rect.angle != 0)
|
|
|
|
{
|
|
|
|
cv::RotatedRect rect_temp = rect;
|
|
|
|
if (rect_temp.size.width > out.img.cols)
|
|
|
|
rect_temp.size.width = out.img.cols;
|
|
|
|
if (rect_temp.size.height > out.img.rows)
|
|
|
|
rect_temp.size.height = out.img.rows;
|
|
|
|
|
|
|
|
cv::Point2f srcTri[4], dstTri[3];
|
|
|
|
rect_temp.points(srcTri);
|
|
|
|
srcTri[0].x -= 1;
|
|
|
|
srcTri[1].x -= 1;
|
|
|
|
srcTri[2].x -= 1;
|
|
|
|
|
|
|
|
int w = rect_temp.size.width;
|
|
|
|
int h = rect_temp.size.height;
|
|
|
|
int x = (out.img.cols - w) / 2;
|
|
|
|
int y = (out.img.rows - h) / 2;
|
|
|
|
dstTri[0] = cv::Point2f(0, h);
|
|
|
|
dstTri[1] = cv::Point2f(0, 0);
|
|
|
|
dstTri[2] = cv::Point2f(w, 0);
|
|
|
|
|
|
|
|
dstROI = out.img(cv::Rect(x, y, w, h) & cv::Rect(0, 0, out.img.cols, out.img.rows));
|
|
|
|
myWarpAffine(in.img, dstROI, cv::getAffineTransform(srcTri, dstTri), dstROI.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, blankColor);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cv::Rect bounding = cv::boundingRect(maxContour);
|
|
|
|
|
|
|
|
if (bounding.width > out.img.cols)
|
|
|
|
{
|
|
|
|
bounding.x += (bounding.width - out.img.cols) / 2;
|
|
|
|
bounding.width = out.img.cols;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bounding.height > out.img.rows)
|
|
|
|
{
|
|
|
|
bounding.y += (bounding.height - out.img.rows) / 2;
|
|
|
|
bounding.height = out.img.rows;
|
|
|
|
}
|
|
|
|
|
|
|
|
dstROI = out.img(cv::Rect((out.img.cols - bounding.width) / 2, (out.img.rows - bounding.height) / 2, bounding.width, bounding.height));
|
|
|
|
in.img(bounding).copyTo(dstROI);
|
|
|
|
|
|
|
|
//cv::imwrite("out.img.bmp", out.img);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fill_bg_)
|
|
|
|
{
|
|
|
|
if (convex_)
|
|
|
|
{
|
|
|
|
hg::convexHull(maxContour, maxContour);
|
|
|
|
contours.clear();
|
|
|
|
contours.push_back(maxContour);
|
|
|
|
}
|
|
|
|
|
|
|
|
cv::Point2f srcTri[4], dstTri[3];
|
|
|
|
int w, h;
|
|
|
|
if (deskew_ && rect.angle != 0)
|
|
|
|
{
|
|
|
|
rect.points(srcTri);
|
|
|
|
srcTri[0].x -= 1;
|
|
|
|
srcTri[1].x -= 1;
|
|
|
|
srcTri[2].x -= 1;
|
|
|
|
w = rect.size.width;
|
|
|
|
h = rect.size.height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//cv::Rect bounding = rect.boundingRect();
|
|
|
|
cv::Rect bounding = cv::boundingRect(maxContour);
|
|
|
|
srcTri[0] = cv::Point(bounding.x, bounding.br().y - 1);
|
|
|
|
srcTri[1] = cv::Point(bounding.x, bounding.y);
|
|
|
|
srcTri[2] = cv::Point(bounding.br().x - 1, bounding.y);
|
|
|
|
w = bounding.width;
|
|
|
|
h = bounding.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
dstTri[0] = cv::Point2f((dstROI.cols - w) / 2 + indent_, (dstROI.rows - h) / 2 + h - indent_);
|
|
|
|
dstTri[1] = cv::Point2f((dstROI.cols - w) / 2 + indent_, (dstROI.rows - h) / 2 + indent_);
|
|
|
|
dstTri[2] = cv::Point2f((dstROI.cols - w) / 2 - indent_ + w, (dstROI.rows - h) / 2 + indent_);
|
|
|
|
cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
|
|
|
|
|
|
|
double* ptr_m = reinterpret_cast<double*>(warp_mat.data);
|
|
|
|
double a = ptr_m[0];
|
|
|
|
double b = ptr_m[1];
|
|
|
|
double c = ptr_m[2];
|
|
|
|
double d = ptr_m[3];
|
|
|
|
double e = ptr_m[4];
|
|
|
|
double f = ptr_m[5];
|
|
|
|
|
|
|
|
int x, y;
|
|
|
|
for (std::vector<cv::Point>& sub : contours)
|
|
|
|
for (cv::Point& p : sub)
|
|
|
|
{
|
|
|
|
x = p.x;
|
|
|
|
y = p.y;
|
|
|
|
p.x = static_cast<int>(a * x + b * y + c);
|
|
|
|
p.y = static_cast<int>(d * x + e * y + f);
|
|
|
|
}
|
|
|
|
|
|
|
|
contours.push_back(std::vector<cv::Point>());
|
|
|
|
contours[contours.size() - 1].push_back(cv::Point(-1, dstROI.rows - 1));
|
|
|
|
contours[contours.size() - 1].push_back(cv::Point(-1, -1));
|
|
|
|
contours[contours.size() - 1].push_back(cv::Point(dstROI.cols, -1));
|
|
|
|
contours[contours.size() - 1].push_back(cv::Point(dstROI.cols, out.img.rows));
|
|
|
|
hg::fillPolys(dstROI, contours, blankColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int auto_crop::set_value(const char* name/*nullptr for all options*/, void* val/*nullptr for restore*/)
|
|
|
|
{
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
|
|
|
if(opt_handler_.count(name))
|
|
|
|
opt_handler_[name](val);
|
|
|
|
else
|
|
|
|
ret = SCANNER_ERR_DEVICE_NOT_SUPPORT;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
int auto_crop::process(std::vector<PROCIMGINFO>& in, std::vector<PROCIMGINFO>& out)
|
|
|
|
{
|
|
|
|
int ret = SCANNER_ERR_OK;
|
|
|
|
|
|
|
|
for(auto& v: in)
|
|
|
|
{
|
|
|
|
PROCIMGINFO o;
|
|
|
|
chronograph watch;
|
|
|
|
|
|
|
|
ret = work(v, o);
|
2024-01-24 09:40:41 +00:00
|
|
|
|
2024-01-24 04:05:05 +00:00
|
|
|
o.info = v.info;
|
|
|
|
o.info.prc_time = watch.elapse_ms();
|
|
|
|
o.info.prc_stage = get_position();
|
|
|
|
o.info.width = o.img.cols;
|
|
|
|
o.info.height = o.img.rows;
|
|
|
|
|
|
|
|
out.push_back(o);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|