code_device/hgdriver/ImageProcess/ImageApplyUV.cpp

316 lines
10 KiB
C++
Raw Permalink Normal View History

2022-05-03 03:56:07 +00:00
#include "ImageApplyUV.h"
using namespace cv;
#define SCA 50
ImageApplyUV::ImageApplyUV() : lut(1, 256, CV_8UC1)
{
}
ImageApplyUV::~ImageApplyUV()
{
}
void ImageApplyUV::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 ImageApplyUV::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, 150, 255, THRESH_BINARY);
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;
findContours1(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 ImageApplyUV::Apply(const cv::Mat& image, const cv::Mat& uv, const cv::RotatedRect& uvRoi, bool isDesaskew, int angle, int pixtype)
{
static int svindex = 0;
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(uvRoi_clone.size.width - 1, 0);
dstTri[2] = cv::Point2f(uvRoi_clone.size.width - 1, uvRoi_clone.size.height - 1);
}
else if (angle == 180)
{
dstTri[0] = cv::Point2f(uvRoi_clone.size.width - 1, 0);
dstTri[1] = cv::Point2f(uvRoi_clone.size.width - 1, uvRoi_clone.size.height - 1);
dstTri[2] = cv::Point2f(0, uvRoi_clone.size.height - 1);
}
else if (angle == 270)
{
dstTri[0] = cv::Point2f(uvRoi_clone.size.width - 1, uvRoi_clone.size.height - 1);
dstTri[1] = cv::Point2f(0, uvRoi_clone.size.height - 1);
dstTri[2] = cv::Point2f(0, 0);
}
else
{
dstTri[0] = cv::Point2f(0, uvRoi_clone.size.height - 1);
dstTri[1] = cv::Point2f(0, 0);
dstTri[2] = cv::Point2f(uvRoi_clone.size.width - 1, 0);
}
cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri);
cv::Mat uv_temp;
cv::warpAffine(uv, uv_temp, warp_mat, cv::Size(uvRoi_clone.size.width, uvRoi_clone.size.height));
//cv::imwrite("uv_temp.jpg", uv_temp);
if (pixtype == 0)//<2F><>ֵͼ
{
cvtColor(uv_temp, uv_temp, cv::COLOR_BGR2GRAY);
cv::threshold(uv_temp, uv_temp, 150, 255, THRESH_OTSU);
}
if (uv_temp.channels() == 1 && dst_uv.channels() == 3)
{
cv::cvtColor(uv_temp(cv::Rect(
uv_temp.cols > dst_uv.cols ? (uv_temp.cols - dst_uv.cols) / 2 : 0,
uv_temp.rows > dst_uv.rows ? (uv_temp.rows - dst_uv.rows) / 2 : 0,
uv_temp.cols > dst_uv.cols ? dst_uv.cols : uv_temp.cols,
uv_temp.rows > dst_uv.rows ? dst_uv.rows : uv_temp.rows)),
dst_uv(cv::Rect(
dst_uv.cols > uv_temp.cols ? (dst_uv.cols - uv_temp.cols) / 2 : 0,
dst_uv.rows > uv_temp.rows ? (dst_uv.rows - uv_temp.rows) / 2 : 0,
dst_uv.cols > uv_temp.cols ? uv_temp.cols : dst_uv.cols,
dst_uv.rows > uv_temp.rows ? uv_temp.rows : dst_uv.rows)), cv::COLOR_GRAY2BGR);
}
else if (uv_temp.channels() == 3 && dst_uv.channels() == 1)
{
cv::cvtColor(uv_temp(cv::Rect(
uv_temp.cols > dst_uv.cols ? (uv_temp.cols - dst_uv.cols) / 2 : 0,
uv_temp.rows > dst_uv.rows ? (uv_temp.rows - dst_uv.rows) / 2 : 0,
uv_temp.cols > dst_uv.cols ? dst_uv.cols : uv_temp.cols,
uv_temp.rows > dst_uv.rows ? dst_uv.rows : uv_temp.rows)),
dst_uv(cv::Rect(
dst_uv.cols > uv_temp.cols ? (dst_uv.cols - uv_temp.cols) / 2 : 0,
dst_uv.rows > uv_temp.rows ? (dst_uv.rows - uv_temp.rows) / 2 : 0,
dst_uv.cols > uv_temp.cols ? uv_temp.cols : dst_uv.cols,
dst_uv.rows > uv_temp.rows ? uv_temp.rows : dst_uv.rows)), cv::COLOR_BGR2GRAY);
}
else
{
uv_temp(cv::Rect(
uv_temp.cols > dst_uv.cols ? (uv_temp.cols - dst_uv.cols) / 2 : 0,
uv_temp.rows > dst_uv.rows ? (uv_temp.rows - dst_uv.rows) / 2 : 0,
uv_temp.cols > dst_uv.cols ? dst_uv.cols : uv_temp.cols,
uv_temp.rows > dst_uv.rows ? dst_uv.rows : uv_temp.rows)).copyTo(dst_uv(cv::Rect(
dst_uv.cols > uv_temp.cols ? (dst_uv.cols - uv_temp.cols) / 2 : 0,
dst_uv.rows > uv_temp.rows ? (dst_uv.rows - uv_temp.rows) / 2 : 0,
dst_uv.cols > uv_temp.cols ? uv_temp.cols : dst_uv.cols,
dst_uv.rows > uv_temp.rows ? uv_temp.rows : dst_uv.rows)));
}
}
else
{
cv::Rect uvBoundingRect = uvRoi_clone.boundingRect();
cv::Rect uvBoundingRect_temp;
if (angle == 90 || angle == 270)
{
uvBoundingRect_temp.x = dst_uv.rows > uvBoundingRect.width ? uvBoundingRect.x : uvBoundingRect.x + (uvBoundingRect.width - dst_uv.rows) / 2;
uvBoundingRect_temp.width = cv::min(dst_uv.rows, uvBoundingRect.width);
uvBoundingRect_temp.y = dst_uv.cols > uvBoundingRect.height ? uvBoundingRect.y : uvBoundingRect.y + (uvBoundingRect.height - dst_uv.cols) / 2;
uvBoundingRect_temp.height = cv::min(dst_uv.cols, uvBoundingRect.height);
}
else
{
uvBoundingRect_temp.x = dst_uv.cols > uvBoundingRect.width ? uvBoundingRect.x : uvBoundingRect.x + (uvBoundingRect.width - dst_uv.cols) / 2;
uvBoundingRect_temp.width = cv::min(dst_uv.cols, uvBoundingRect.width);
uvBoundingRect_temp.y = dst_uv.rows > uvBoundingRect.height ? uvBoundingRect.y : uvBoundingRect.y + (uvBoundingRect.height - dst_uv.rows) / 2;
uvBoundingRect_temp.height = cv::min(dst_uv.rows, uvBoundingRect.height);
}
int offset_left = 0, offset_right = 0, offset_top = 0, offset_bottom = 0;
if (uvBoundingRect_temp.x < 0)
{
offset_left = -uvBoundingRect_temp.x;
uvBoundingRect_temp.x = 0;
uvBoundingRect_temp.width -= offset_left;
}
if (uvBoundingRect_temp.y < 0)
{
offset_top = -uvBoundingRect_temp.y;
uvBoundingRect_temp.y = 0;
uvBoundingRect_temp.height -= offset_top;
}
if (uvBoundingRect_temp.br().x >= uv.cols)
{
offset_right = uvBoundingRect_temp.br().x - uv.cols + 1;
uvBoundingRect_temp.width -= offset_right;
}
if (uvBoundingRect_temp.br().y >= uv.rows)
{
offset_bottom = uvBoundingRect_temp.br().y - uv.rows + 1;
uvBoundingRect_temp.height -= offset_bottom;
}
cv::Mat uv_roi = uv(uvBoundingRect_temp).clone();
if (dst_uv.channels() == 1)//<2F>Ҷ<EFBFBD>
{
cv::cvtColor(uv_roi, uv_roi, cv::COLOR_BGR2GRAY);
if (pixtype == 0)//<2F><>ֵͼ
cv::threshold(uv_roi, uv_roi, 150, 255, THRESH_OTSU);
}
uv_roi.copyTo(dst_uv(cv::Rect((dst_uv.cols - uv_roi.cols + offset_left) / 2, (dst_uv.rows - uv_roi.rows + offset_top) / 2, uv_roi.cols, uv_roi.rows)));
}
//imwrite("D:\\dst" + std::to_string(svindex) + ".jpg", dst);
return dst;
}
void ImageApplyUV::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];
}
}
}
}
void ImageApplyUV::findContours1(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
{
CvMat c_image;
CV_DbgAssert(src.dims <= 2);
c_image = cvMat(src.rows, src.dims == 1 ? 1 : src.cols, src.type(), src.data);
c_image.step = (int)src.step[0];
c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG);
cv::MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint({ offset.x,offset.y }));
if (!_ccontours)
{
contours.clear();
return;
}
cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
size_t total = all_contours.size();
contours.resize(total);
cv::SeqIterator<CvSeq*> it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
int count = c->total;
int* data = new int[static_cast<size_t>(count * 2)];
cvCvtSeqToArray(c, data);
for (int j = 0; j < count; j++)
contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
delete[] data;
}
hierarchy.resize(total);
it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
}
storage.release();
}
cv::Scalar ImageApplyUV::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;
}