#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(cv::max(0, cv::min(i - m_contrast, 127))); else ptr[i] = static_cast(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> contours; std::vector hierarchy; hg::findContours(uv_resize, contours, hierarchy, cv::RETR_EXTERNAL); std::map 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 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(j, i)) { uchar* color = image_roi.ptr(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(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; }