#include "CISTestImageProcess.h" int CISTestImageProcess::test(const cv::Mat& image, CISTestResult& result) { #if 0 //std::vector marks; //int res = findMarks(image, marks); //return res; result.scaleXY1 = -1; result.scaleXY2 = -1; result.scaleXY3 = -1; if (image.channels() != 3) return -1; //图片不是彩色图 int res = 0; cv::Mat hsv; cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV_FULL); std::vector hsv_channels; cv::split(hsv, hsv_channels); cv::Mat mask_s, range_h, range_temp; cv::inRange(hsv_channels[1], 110, 255, mask_s); //饱和度在[50, 220]的像素 //cv::imwrite("range1.jpg", mask_s); cv::inRange(hsv_channels[0], 0, 84, range_h); //饱和度在[220, 255]的像素 cv::inRange(hsv_channels[0], 213, 255, range_temp); //饱和度在[220, 255]的像素 range_h &= mask_s; range_h |= range_temp & mask_s; //cv::imwrite("range3.jpg", range_h); res = findEllipse(range_h, result.scaleXY1); if (res != 0) return -2; cv::inRange(hsv_channels[0], 30, 140, range_h); //饱和度在[220, 255]的像素 range_h &= mask_s; //cv::imwrite("range4.jpg", range_h); res = findEllipse(range_h, result.scaleXY2); if (res != 0) return -2; cv::inRange(hsv_channels[0], 128, 213, range_h); //饱和度在[220, 255]的像素 range_h &= mask_s; //cv::imwrite("range5.jpg", range_h); res = findEllipse(range_h, result.scaleXY3); if (res != 0) return -2; #else cv::Mat thre; if (image.channels() == 3) cv::cvtColor(image, thre, cv::COLOR_BGR2GRAY); else thre = image.clone(); cv::threshold(thre, thre, 127, 255, cv::THRESH_BINARY); std::vector> contours; std::vector hierarchy; findContours(thre, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE); std::vector contour; for (size_t i = 0; i < contours.size(); i++) { if (hierarchy[i][3] == -1) continue; cv::Rect rect = cv::boundingRect(contours[i]); if (rect.width < 100) continue; else { contour = contours[i]; break; } } if (contour.size() < 3) return -2; cv::RotatedRect box = cv::fitEllipse(contour); if (box.angle < -45) { box.angle += 90; float temp = box.size.width; box.size.width = box.size.height; box.size.height = temp; } if (box.angle < -45) { box.angle += 90; float temp = box.size.width; box.size.width = box.size.height; box.size.height = temp; } if (box.angle > 45) { box.angle -= 90; float temp = box.size.width; box.size.width = box.size.height; box.size.height = temp; } if (box.angle > 45) { box.angle -= 90; float temp = box.size.width; box.size.width = box.size.height; box.size.height = temp; } result.w = box.size.width; result.h = box.size.height; result.scaleXY = box.size.width / box.size.height; #endif return 0; } CISTestImageProcess::CISTestImageProcess() { } void CISTestImageProcess::findContours(const cv::Mat& src, std::vector>& contours, std::vector& hierarchy, int retr, int method, cv::Point offset) { #if CV_VERSION_REVISION <= 6 CvMat c_image = src; #else CvMat c_image; c_image = cvMat(src.rows, src.cols, src.type(), src.data); c_image.step = src.step[0]; c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG); #endif cv::MemStorage storage(cvCreateMemStorage()); CvSeq* _ccontours = nullptr; #if CV_VERSION_REVISION <= 6 cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset)); #else cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint{ offset.x, offset.y }); #endif if (!_ccontours) { contours.clear(); return; } cv::Seq all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); size_t total = all_contours.size(); contours.resize(total); cv::SeqIterator it = all_contours.begin(); for (size_t i = 0; i < total; i++, ++it) { CvSeq* c = *it; reinterpret_cast(c)->color = static_cast(i); int count = c->total; int* data = new int[static_cast(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(c->h_next)->color : -1; int h_prev = c->h_prev ? reinterpret_cast(c->h_prev)->color : -1; int v_next = c->v_next ? reinterpret_cast(c->v_next)->color : -1; int v_prev = c->v_prev ? reinterpret_cast(c->v_prev)->color : -1; hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev); } storage.release(); } void CISTestImageProcess::convexHull(const std::vector& src, std::vector& dst, bool clockwise) { CvMemStorage* storage = cvCreateMemStorage(); // CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage); //ptseqstorage //将src的点集填充至ptseq for (const cv::Point& item : src) { CvPoint p; p.x = item.x; p.y = item.y; cvSeqPush(ptseq, &p); } //获取轮廓点 CvSeq* hull = cvConvexHull2(ptseq, nullptr, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0); if (hull == nullptr) { //释放storage cvReleaseMemStorage(&storage); return; } //填充dst dst.clear(); for (int i = 0, hullCount = hull->total; i < hullCount; i++) dst.push_back(**CV_GET_SEQ_ELEM(CvPoint*, hull, i)); //释放storage cvReleaseMemStorage(&storage); } int CISTestImageProcess::findPaperContour(const std::vector>& contours, const std::vector& hierarchy, cv::RotatedRect& paperRect) { std::vector maxContour; if (contours.size() < 1) return {}; for (size_t i = 0, length = hierarchy.size(); i < length; i++) if (hierarchy[i][3] == -1) for (const auto& item : contours[i]) maxContour.push_back(item); if (maxContour.size() == 0) return -1; paperRect = cv::minAreaRect(maxContour); if (paperRect.angle < -45) { paperRect.angle += 90; float temp = paperRect.size.width; paperRect.size.width = paperRect.size.height; paperRect.size.height = temp; } if (paperRect.angle > 45) { paperRect.angle -= 90; float temp = paperRect.size.width; paperRect.size.width = paperRect.size.height; paperRect.size.height = temp; } return 0; } int CISTestImageProcess::classfiyContours(const std::vector>& contours, std::vector>& marks, std::vector>& colorBlocks, std::vector>& grayBlocks) { marks.clear(); colorBlocks.clear(); grayBlocks.clear(); for (size_t i = 0; i < contours.size(); i++) { double area = cv::contourArea(contours[i]); } return 0; } int CISTestImageProcess::findEllipse(const cv::Mat& image, double& scale_xy, double areaThre) { //cv::imwrite("range2.jpg", image); std::vector> contours; std::vector hierarchy; findContours(image, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE); std::vector maxContour; for (std::vector>::iterator iter = contours.begin(); iter != contours.end(); iter++) if (cv::contourArea(*iter) > areaThre) for (const auto& item : *iter) maxContour.push_back(item); convexHull(maxContour, maxContour); if (maxContour.size() < 3) return -1; cv::RotatedRect box = cv::fitEllipse(maxContour); if (box.angle < -45) { box.angle += 90; float temp = box.size.width; box.size.width = box.size.height; box.size.height = temp; } if (box.angle > 45) { box.angle -= 90; float temp = box.size.width; box.size.width = box.size.height; box.size.height = temp; } scale_xy = box.size.width / box.size.height; return 0; }