mirror of http://192.168.1.51:8099/lmh188/twain3.0
183 lines
5.2 KiB
C++
183 lines
5.2 KiB
C++
|
#include "ImageApplyAutoCrop.h"
|
||
|
#include "ImageProcess_Public.h"
|
||
|
|
||
|
#define RE 2
|
||
|
|
||
|
CImageApplyAutoCrop::CImageApplyAutoCrop()
|
||
|
: m_isCrop(false)
|
||
|
, m_isDesaskew(false)
|
||
|
, m_isFillBlank(false)
|
||
|
, m_isConvexHull(true)
|
||
|
, m_threshold(40)
|
||
|
, m_noise(2)
|
||
|
, m_indent(5)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CImageApplyAutoCrop::CImageApplyAutoCrop(bool isCrop, bool isDesaskew, bool isFillBlank, const cv::Size& fixedSize, bool isConvex, double threshold, int noise, int indent)
|
||
|
: m_isCrop(isCrop)
|
||
|
, m_isDesaskew(isDesaskew)
|
||
|
, m_isFillBlank(isFillBlank)
|
||
|
, m_isConvexHull(isConvex)
|
||
|
, m_threshold(threshold)
|
||
|
, m_noise(noise)
|
||
|
, m_indent(indent)
|
||
|
, m_fixedSize(fixedSize)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CImageApplyAutoCrop::~CImageApplyAutoCrop()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void CImageApplyAutoCrop::apply(cv::Mat& pDib, int side)
|
||
|
{
|
||
|
#ifdef LOG
|
||
|
FileTools::write_log("imgprc.txt", "enter CImageApplyAutoCrop apply");
|
||
|
#endif // LOG
|
||
|
if (pDib.empty())
|
||
|
{
|
||
|
#ifdef LOG
|
||
|
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply");
|
||
|
#endif // LOG
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
cv::Mat src = pDib;
|
||
|
cv::Mat dst;
|
||
|
cv::Mat src_resize;
|
||
|
cv::resize(src, src_resize, cv::Size(src.cols / RE, src.rows / RE));
|
||
|
cv::Mat scale_mat;
|
||
|
cv::Mat thre(src_resize.size(), CV_8UC1);
|
||
|
hg::threshold_Mat(src_resize, thre, m_threshold);
|
||
|
|
||
|
if (m_noise > RE)
|
||
|
{
|
||
|
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(m_noise / RE, m_noise / RE));
|
||
|
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element);
|
||
|
}
|
||
|
std::vector<cv::Vec4i> hierarchy;
|
||
|
std::vector<std::vector<cv::Point>> contours;
|
||
|
|
||
|
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
|
||
|
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
|
||
|
|
||
|
for (cv::Point& item : maxContour)
|
||
|
{
|
||
|
item.x = item.x * RE - RE / 2;
|
||
|
item.y = item.y * RE - RE / 2;
|
||
|
}
|
||
|
|
||
|
if (maxContour.size() == 0)
|
||
|
{
|
||
|
thre.release();
|
||
|
#ifdef LOG
|
||
|
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply");
|
||
|
#endif // LOG
|
||
|
return;
|
||
|
}
|
||
|
thre.release();
|
||
|
dst.release();
|
||
|
|
||
|
cv::RotatedRect rect = hg::getBoundingRect(maxContour);
|
||
|
|
||
|
if (m_isDesaskew)
|
||
|
{
|
||
|
cv::Point2f srcTri[4];
|
||
|
cv::Point2f dstTri[3];
|
||
|
rect.points(srcTri);
|
||
|
|
||
|
dstTri[0] = cv::Point2f(0, rect.size.height - 1);
|
||
|
dstTri[1] = cv::Point2f(0, 0);
|
||
|
dstTri[2] = cv::Point2f(rect.size.width - 1, 0);
|
||
|
|
||
|
cv::Mat warp_mat;
|
||
|
warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
||
|
cv::warpAffine(src, dst, warp_mat, rect.size);
|
||
|
}
|
||
|
else
|
||
|
dst = src(rect.boundingRect() & cv::Rect(0, 0, src.cols, src.rows));
|
||
|
|
||
|
if (m_isFillBlank)
|
||
|
{
|
||
|
cv::Mat thre_dst;
|
||
|
hg::threshold_Mat(dst, thre_dst, m_threshold);
|
||
|
cv::erode(thre_dst, thre_dst, cv::Mat(), cv::Point(-1, -1), m_indent);
|
||
|
hierarchy.clear();
|
||
|
contours.clear();
|
||
|
maxContour.clear();
|
||
|
|
||
|
hg::findContours(thre_dst, contours, hierarchy, cv::RETR_EXTERNAL);
|
||
|
maxContour = hg::getMaxContour(contours, hierarchy);
|
||
|
if (m_isConvexHull)
|
||
|
hg::convexHull(maxContour, maxContour);
|
||
|
|
||
|
contours.clear();
|
||
|
contours.resize(2);
|
||
|
contours[0] = maxContour;
|
||
|
contours[1].push_back(cv::Point(0, dst.rows - 1));
|
||
|
contours[1].push_back(cv::Point(0, 0));
|
||
|
contours[1].push_back(cv::Point(dst.cols - 1, 0));
|
||
|
contours[1].push_back(cv::Point(dst.cols - 1, dst.rows - 1));
|
||
|
|
||
|
hg::fillPolys(dst, contours, cv::Scalar(255, 255, 255));
|
||
|
}
|
||
|
|
||
|
pDib.release();
|
||
|
if ((m_isCrop && side == 0) || (side == 1 && m_fixedSize.width * m_fixedSize.height == 0))
|
||
|
pDib = dst.clone();
|
||
|
else
|
||
|
{
|
||
|
if (m_isCrop && side == 1 && !m_fixedSize.empty())
|
||
|
if (std::abs(m_fixedSize.width - dst.cols) > 50 || std::abs(m_fixedSize.height - dst.rows) > 50)
|
||
|
{
|
||
|
pDib = dst.clone();
|
||
|
#ifdef LOG
|
||
|
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply");
|
||
|
#endif // LOG
|
||
|
return;
|
||
|
}
|
||
|
pDib = cv::Mat(m_fixedSize, dst.type(), m_isFillBlank ? cv::Scalar(255, 255, 255) : cv::Scalar(0, 0, 0));
|
||
|
|
||
|
cv::Rect roi;
|
||
|
roi.x = dst.cols > pDib.cols ? (dst.cols - pDib.cols) / 2 : 0;
|
||
|
roi.width = cv::min(pDib.cols, dst.cols);
|
||
|
roi.y = dst.rows > pDib.rows ? (dst.rows - pDib.rows) / 2 : 0;
|
||
|
roi.height = cv::min(pDib.rows, dst.rows);
|
||
|
cv::Rect rect((pDib.cols - roi.width) / 2, (pDib.rows - roi.height) / 2, roi.width, roi.height);
|
||
|
#if 0
|
||
|
std::string outrectinfo ="copy to rect x: "+std::to_string(rect.x) + "y: "+std::to_string(rect.y) + "width: "+std::to_string(rect.width) + "height: "+std::to_string(rect.height);
|
||
|
std::string outroiinfo = "roi x: " + std::to_string(roi.x) + "y: " + std::to_string(roi.y) + "width: " + std::to_string(roi.width) + "height: " + std::to_string(roi.height);
|
||
|
std::string dstsize = "dst size: width:" + std::to_string(dst.cols) + "height: " + std::to_string(dst.rows);
|
||
|
std::string pDibszie= "pDib size: width: " + std::to_string(pDib.cols) + "height: " + std::to_string(pDib.rows);
|
||
|
FileTools::write_log("imgprc.txt", dstsize);
|
||
|
FileTools::write_log("imgprc.txt", pDibszie);
|
||
|
FileTools::write_log("imgprc.txt", outrectinfo);
|
||
|
FileTools::write_log("imgprc.txt", outroiinfo);
|
||
|
#endif // LOG
|
||
|
dst(roi).copyTo(pDib(rect));
|
||
|
|
||
|
}
|
||
|
#ifdef LOG
|
||
|
FileTools::write_log("imgprc.txt", "exit CImageApplyAutoCrop apply8");
|
||
|
#endif // LOG
|
||
|
}
|
||
|
|
||
|
void CImageApplyAutoCrop::apply(std::vector<cv::Mat>& mats, bool isTwoSide)
|
||
|
{
|
||
|
if (mats.empty()) return;
|
||
|
|
||
|
apply(mats[0], 0);
|
||
|
|
||
|
if (isTwoSide && mats.size() > 1)
|
||
|
{
|
||
|
cv::Size dSize = m_fixedSize;
|
||
|
if (!mats[0].empty())
|
||
|
m_fixedSize = mats[0].size();
|
||
|
|
||
|
apply(mats[1], 1);
|
||
|
|
||
|
if (!mats[0].empty())
|
||
|
m_fixedSize = dSize;
|
||
|
}
|
||
|
}
|