mirror of http://192.168.1.51:8099/lmh188/twain3
187 lines
5.4 KiB
C++
187 lines
5.4 KiB
C++
#include "ImageApplyUVMerge.h"
|
|
#include "ImageProcess_Public.h"
|
|
using namespace cv;
|
|
#define SCA 50
|
|
|
|
CImageApplyUVMerge::CImageApplyUVMerge(): lut(1, 256, CV_8UC1)
|
|
{
|
|
}
|
|
|
|
CImageApplyUVMerge::~CImageApplyUVMerge()
|
|
{
|
|
}
|
|
|
|
void CImageApplyUVMerge::update_lutData(int contrast)
|
|
{
|
|
unsigned char* ptr = lut.data;
|
|
int m_contrast = cv::max(-127, cv::min(contrast, 127));
|
|
for (int i = 0; i < 256; i++)
|
|
{
|
|
//update contrast
|
|
if (i < 128)
|
|
ptr[i] = static_cast<unsigned char>(cv::max(0, cv::min(i - m_contrast, 127)));
|
|
else
|
|
ptr[i] = static_cast<unsigned char>(cv::max(127, cv::min(i + m_contrast, 255)));
|
|
}
|
|
}
|
|
|
|
void CImageApplyUVMerge::Apply(cv::Mat& image, const cv::Mat& uv, int dpi, int thresh)
|
|
{
|
|
update_lutData(12);
|
|
cv::LUT(uv, lut, uv);
|
|
Mat uv_resize;
|
|
cv::resize(uv, uv_resize, cv::Size(uv.cols * SCA / dpi, uv.rows * SCA / dpi));
|
|
if (uv_resize.channels() == 3)
|
|
cv::cvtColor(uv_resize, uv_resize, cv::COLOR_BGR2GRAY);
|
|
cv::threshold(uv_resize, uv_resize, 0, 255, THRESH_OTSU);
|
|
cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1500 / dpi, 1500 / dpi));
|
|
cv::dilate(uv_resize, uv_resize, element);
|
|
std::vector<std::vector<cv::Point>> contours;
|
|
std::vector<cv::Vec4i> hierarchy;
|
|
hg::findContours(uv_resize, contours, hierarchy, cv::RETR_EXTERNAL);
|
|
|
|
std::map<int, cv::Scalar> map_color;
|
|
for (int i = 0; i < contours.size(); i++)
|
|
{
|
|
cv::Rect roi = cv::boundingRect(contours[i]);
|
|
roi.x *= dpi / SCA;
|
|
roi.y *= dpi / SCA;
|
|
roi.width *= dpi / SCA;
|
|
roi.height *= dpi / SCA;
|
|
|
|
purgeQR_kernal(image, roi, map_color, dpi, thresh);
|
|
}
|
|
}
|
|
|
|
cv::Mat CImageApplyUVMerge::Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle)
|
|
{
|
|
if (uvRoi.size.width == 0) return cv::Mat();
|
|
|
|
cv::RotatedRect uvRoi_clone = uvRoi;
|
|
cv::Mat dst = cv::Mat::zeros(image.rows > image.cols ? image.rows : (image.rows * 2), image.cols > image.rows ? image.cols : (image.cols * 2), image.type());
|
|
image.copyTo(dst(cv::Rect(0, 0, image.cols, image.rows)));
|
|
|
|
cv::Mat dst_uv = dst(cv::Rect(image.rows > image.cols ? image.cols : 0, image.rows > image.cols ? 0 : image.rows, image.cols, image.rows));
|
|
if (isDesaskew)
|
|
{
|
|
cv::Point2f srcTri[4];
|
|
cv::Point2f dstTri[3];
|
|
uvRoi_clone.points(srcTri);
|
|
|
|
|
|
if (angle == 90)
|
|
{
|
|
dstTri[0] = cv::Point2f(0, 0);
|
|
dstTri[1] = cv::Point2f(dst_uv.cols - 1, 0);
|
|
dstTri[2] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
|
|
}
|
|
else if (angle == 180)
|
|
{
|
|
dstTri[0] = cv::Point2f(dst_uv.cols - 1, 0);
|
|
dstTri[1] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
|
|
dstTri[2] = cv::Point2f(0, dst_uv.rows - 1);
|
|
}
|
|
else if (angle == 270)
|
|
{
|
|
dstTri[0] = cv::Point2f(dst_uv.cols - 1, dst_uv.rows - 1);
|
|
dstTri[1] = cv::Point2f(0, dst_uv.rows - 1);
|
|
dstTri[2] = cv::Point2f(0, 0);
|
|
}
|
|
else
|
|
{
|
|
dstTri[0] = cv::Point2f(0, dst_uv.rows - 1);
|
|
dstTri[1] = cv::Point2f(0, 0);
|
|
dstTri[2] = cv::Point2f(dst_uv.cols - 1, 0);
|
|
}
|
|
|
|
cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri);
|
|
if (uv.channels() == 1 && dst_uv.channels() == 3)
|
|
{
|
|
cv::Mat uv_temp;
|
|
cv::warpAffine(uv, uv_temp, warp_mat, dst_uv.size());
|
|
cv::cvtColor(uv_temp, dst_uv, cv::COLOR_GRAY2BGR);
|
|
}
|
|
else
|
|
cv::warpAffine(uv, dst_uv, warp_mat, dst_uv.size());
|
|
}
|
|
else
|
|
{
|
|
cv::Rect uvBoundingRect = uvRoi_clone.boundingRect();
|
|
|
|
cv::Rect roi_dst_right;
|
|
roi_dst_right.x = dst_uv.cols > uvBoundingRect.width ? (dst_uv.cols - uvBoundingRect.width) / 2 : 0;
|
|
roi_dst_right.width = cv::min(dst_uv.cols, uvBoundingRect.width);
|
|
roi_dst_right.y = dst_uv.rows > uvBoundingRect.height ? (dst_uv.rows - uvBoundingRect.height) / 2 : 0;
|
|
roi_dst_right.height = cv::min(dst_uv.rows, uvBoundingRect.height);
|
|
|
|
cv::Rect roi_uv_BoundingRect((uvBoundingRect.width - roi_dst_right.width) / 2,
|
|
(uvBoundingRect.height - roi_dst_right.height) / 2, roi_dst_right.width, roi_dst_right.height);
|
|
|
|
Mat uvCrop = (uv(uvBoundingRect))(roi_uv_BoundingRect);
|
|
if (uvCrop.channels() == 1 && dst_uv.channels() == 3)
|
|
cv::cvtColor(uvCrop, uvCrop, cv::COLOR_GRAY2BGR);
|
|
uvCrop.copyTo(dst_uv(roi_dst_right));
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
|
|
void CImageApplyUVMerge::purgeQR_kernal(cv::Mat& image, const cv::Rect& roi, std::map<int, cv::Scalar> map_color, int dpi, int threshold)
|
|
{
|
|
cv::Mat image_roi = image(roi);
|
|
cv::Mat mask;
|
|
cv::cvtColor(image_roi, mask, cv::COLOR_BGR2GRAY);
|
|
cv::threshold(mask, mask, 127, 255, cv::THRESH_OTSU);
|
|
cv::Mat image_resize;
|
|
cv::resize(image, image_resize, cv::Size(image.cols, 800));
|
|
|
|
for (int i = 0, cols = image_roi.cols, rows = image_roi.rows; i < cols; i++)
|
|
{
|
|
cv::Scalar color_fill;
|
|
if (map_color.find(i + roi.x) == map_color.end())
|
|
{
|
|
color_fill = getColor(image_resize, roi.x + i, threshold);
|
|
map_color[i + roi.x] = color_fill;
|
|
}
|
|
else
|
|
color_fill = map_color[i + roi.x];
|
|
|
|
for (int j = 0; j < rows; j++)
|
|
{
|
|
if (*mask.ptr<uchar>(j, i))
|
|
{
|
|
uchar* color = image_roi.ptr<uchar>(j, i);
|
|
color[0] = color_fill[0];
|
|
color[1] = color_fill[1];
|
|
color[2] = color_fill[2];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
cv::Scalar CImageApplyUVMerge::getColor(const cv::Mat& image, int col, int threshold)
|
|
{
|
|
cv::Scalar color(0, 0, 0);
|
|
int num = 0;
|
|
|
|
for (int i = 0, length = image.rows; i < length; i++)
|
|
{
|
|
const uchar* ptr = image.ptr<uchar>(i, col);
|
|
int gray = (ptr[0] * 30 + ptr[1] * 59 + ptr[2] * 11) / 100;
|
|
if (gray > threshold)
|
|
{
|
|
color[0] += ptr[0];
|
|
color[1] += ptr[1];
|
|
color[2] += ptr[2];
|
|
num++;
|
|
}
|
|
}
|
|
|
|
if (num)
|
|
color /= num;
|
|
else
|
|
color[0] = color[1] = color[2] = 255;
|
|
|
|
return color;
|
|
}
|