#include "ImageApplyMarkCrop.h" #include "ImageProcess_Public.h" #define RE 2 //#define DRAW #ifdef NOT_USE CImageApplyMarkCrop::CImageApplyMarkCrop(CImageApplyMarkCrop::DeviceModel device, bool isCropped, double threshold, int noise, CImageApplyMarkCrop::DPI dpi, DirectionMethod direction) : m_device(device) , m_b_isCropped(isCropped) , m_threshold(120) , m_noise(noise) , m_dpi(dpi) , m_range(30, 55) , m_direction(direction) { } int CImageApplyMarkCrop::apply(const cv::Mat& src, cv::Mat& dst, Orientation markOri, bool barCode, int& angle) { if (src.empty()) return -1; cv::Mat src_resize; if (m_device == DeviceModel::G400) cv::resize(src, src_resize, cv::Size(src.cols / RE, src.rows / RE)); else cv::resize(src, src_resize, cv::Size(src.cols / 3, src.rows / RE)); cv::Mat scale_mat; cv::Mat thre(src_resize.size(), CV_8UC1); hg::threshold_Mat(src_resize, thre, m_threshold); #ifdef DRAW cv::imwrite("thre.bmp", thre); #endif std::vector hierarchy; std::vector> contours; hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); std::vector maxContour = hg::getMaxContour(contours, hierarchy); float scale = m_device == DeviceModel::G300 ? 3 : RE; if (maxContour.size() == 0) { thre.release(); return -1; } //thre.release(); //dst.release(); cv::RotatedRect rect = hg::getBoundingRect(maxContour); cv::Point2f vertex[4]; rect.points(vertex); std::vector> marks; std::vector rrects; hg::threshold_Mat(src_resize, thre, m_threshold); cv::bitwise_not(thre, thre); contours.clear(); hierarchy.clear(); hg::findContours(thre, contours, hierarchy, cv::RETR_LIST); findMarks(contours, rect, cv::Range(m_range.start / RE, m_range.end / RE), marks, rrects); if (marks.size() < 3) return -2; #ifdef DRAW for (int i = 0; i < marks.size(); i++) cv::circle(thre, marks[i][0], 30, cv::Scalar(255)); cv::imwrite("contour.bmp", thre); #endif maxContour.clear(); for (const std::vector& mark : marks) for (const cv::Point& p : mark) maxContour.push_back(p); if (rrects.size() == 3) { double distance1 = hg::distanceP2P(rrects[0].center, rrects[1].center); double distance2 = hg::distanceP2P(rrects[1].center, rrects[2].center); double distance3 = hg::distanceP2P(rrects[2].center, rrects[0].center); if (distance1 > distance2 && distance1 > distance3) maxContour.push_back(((rrects[0].center + rrects[1].center) / 2 * 3 - rrects[2].center) / 2); else if (distance2 > distance1 && distance2 > distance3) maxContour.push_back(((rrects[1].center + rrects[2].center) / 2 * 3 - rrects[0].center) / 2); else maxContour.push_back(((rrects[2].center + rrects[0].center) / 2 * 3 - rrects[1].center) / 2); } for (cv::Point& item : maxContour) item *= scale; rect = hg::getBoundingRect(maxContour); rect.points(vertex); cv::Point2f focus; Orientation ori; for (size_t i = 0; i < rrects.size(); i++) for (size_t j = i + 1; j < rrects.size(); j++) if (rrects[i].size.area() < rrects[j].size.area()) { cv::RotatedRect rect_remp = rrects[j]; rrects[j] = rrects[i]; rrects[i] = rect_remp; } for (cv::RotatedRect& item : rrects) item.center *= scale; if (m_direction == DirectionMethod::Multilateral) { if (rrects.size() < 4) return -3; for (int i = 0; i < 5; i++) focus += rrects[i].center; focus /= 5; float dis_top = hg::distanceP2L(focus, vertex[1], vertex[2]); float dis_bottom = hg::distanceP2L(focus, vertex[0], vertex[3]); float dis_left = hg::distanceP2L(focus, vertex[0], vertex[1]); float dis_right = hg::distanceP2L(focus, vertex[2], vertex[3]); float dis_min = cv::min(dis_top, cv::min(dis_bottom, cv::min(dis_left, dis_right))); if (dis_top == dis_min) ori = Top_RB; else if (dis_bottom == dis_min) ori = Bottom_LT; else if (dis_left == dis_min) ori = Left_RT; else ori = Right_LB; } else if (m_direction == DirectionMethod::Trilateral_7Net) { for (int i = 0; i < 3; i++) focus += rrects[i].center; focus /= 3; float dis_top = hg::distanceP2L(focus, vertex[1], vertex[2]); float dis_bottom = hg::distanceP2L(focus, vertex[0], vertex[3]); float dis_left = hg::distanceP2L(focus, vertex[0], vertex[1]); float dis_right = hg::distanceP2L(focus, vertex[2], vertex[3]); float dis_min_lr = cv::min(dis_left, dis_right); float dis_min_tb = cv::min(dis_top, dis_bottom); if (dis_min_lr == dis_right && dis_min_tb == dis_bottom) ori = Bottom_LT; else if (dis_min_lr == dis_left && dis_min_tb == dis_top) ori = Top_RB; else if (dis_min_lr == dis_right && dis_min_tb == dis_top) ori = Right_LB; else ori = Left_RT; } cv::Point2f srcTri[4]; cv::Point2f dstTri[3]; rect.points(srcTri); if (m_device == DeviceModel::G300) for (cv::Point2f& p : srcTri) p.y = p.y * RE / m_device; cv::Size temp_size; float width = rect.size.width; float height = hg::distanceP2P(srcTri[0], srcTri[1]); if (markOri == Default || markOri == ori) { dstTri[0] = cv::Point2f(0, height - 1); dstTri[1] = cv::Point2f(0, 0); dstTri[2] = cv::Point2f(width - 1, 0); temp_size.width = width; temp_size.height = height; angle = 0; } else if (markOri - ori == -3 || markOri - ori == 1) { dstTri[0] = cv::Point2f(0, 0); dstTri[1] = cv::Point2f(height - 1, 0); dstTri[2] = cv::Point2f(height - 1, width - 1); temp_size.width = height; temp_size.height = width; angle = -90; } else if (markOri - ori == -2 || markOri - ori == 2) { dstTri[0] = cv::Point2f(width - 1, 0); dstTri[1] = cv::Point2f(width - 1, height - 1); dstTri[2] = cv::Point2f(0, height - 1); temp_size.width = width; temp_size.height = height; angle = 180; } else if (markOri - ori == -1 || markOri - ori == 3) { dstTri[0] = cv::Point2f(height - 1, width - 1); dstTri[1] = cv::Point2f(0, width - 1); dstTri[2] = cv::Point2f(0, 0); temp_size.width = height; temp_size.height = width; angle = 90; } if (m_b_isCropped) { cv::Mat warp_mat; warp_mat = cv::getAffineTransform(srcTri, dstTri); cv::warpAffine(src, dst, warp_mat, temp_size); } else { if (angle == 0) dst = src.clone(); else if (angle == 90) { cv::transpose(src, dst); cv::flip(dst, dst, 0); } else if (angle == -90) { cv::transpose(src, dst); cv::flip(dst, dst, 1); } else { cv::flip(src, dst, 0); cv::flip(dst, dst, 1); } } //如果需要判断条码 if (barCode) { //cv::imwrite("dst.bmp", dst); if (dst.cols < 600 || dst.rows < 400) return -4; if (!isContainBarCode(dst(cv::Rect(0, 0, 600, 400)))) return -5; } return 0; #ifdef DRAW cv::imwrite("dst.bmp", dst); #endif } void CImageApplyMarkCrop::findMarks(const std::vector>& contours, const cv::RotatedRect& region, const cv::Range& range, std::vector>& marks, std::vector& rrect) { cv::RotatedRect region_outside = region; cv::RotatedRect region_inside = region; region_inside.size = cv::Size2f(region.size.width * 0.9, region.size.height * 0.9); cv::Point2f outside[4], inside[4]; region_outside.points(outside); region_inside.points(inside); std::vector v_outside, v_inside; for (size_t i = 0; i < 4; i++) { v_outside.push_back(cv::Point(outside[i].x, outside[i].y)); v_inside.push_back(cv::Point(inside[i].x, inside[i].y)); } for (size_t i = 0, length = contours.size(); i < length; i++) { std::vector contour = contours[i]; cv::RotatedRect rect = cv::minAreaRect(contour); double area = cv::contourArea(contour); if (rect.size.width < range.start || rect.size.height < range.start || rect.size.width > range.end || rect.size.height > range.end) continue; if (rect.size.width * rect.size.height < 40 / RE) continue; if (cv::pointPolygonTest(v_outside, rect.center, true) > 0 && cv::pointPolygonTest(v_inside, rect.center, true) < 0) { marks.push_back(contour); rrect.push_back(rect); } } } bool CImageApplyMarkCrop::isContainBarCode(const cv::Mat& image) { cv::Mat thre; hg::threshold_Mat(image, thre, 127); cv::bitwise_not(thre, thre); cv::Mat element = cv::getStructuringElement(cv::MorphShapes::MORPH_RECT, cv::Size(20, 1)); cv::morphologyEx(thre, thre, cv::MorphTypes::MORPH_DILATE, element); //cv::imwrite("barCode.bmp", thre); std::vector hierarchy; std::vector> contours; hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL); for (size_t i = 0; i < contours.size(); i++) { cv::Rect rect = cv::boundingRect(contours[i]); if (rect.width > 250 && rect.height > 50) return true; } return false; } #endif //