//#include #include "ImgLocateDryChemistry.h" #include "Comparer.h" #include "ImageLocation.h" using namespace std; using namespace cv; PaperConfig::PaperConfig() { PaperConfig(0,0, 0, 0.0, 0.0, 0.0, 0.0, 0.0); } PaperConfig::PaperConfig(int pst,int i, int s, double f, double st, double d, double r, double l) { paperSpatialType = pst; distTimes = d; itemsNum = i; slicesNum = s; firstPos = f; step = st; whRRatio = r; whLRatio = l; } void PaperConfig::Init() { paperSpatialType = 0; distTimes = 0.0;//21.3 itemsNum = 0; slicesNum = 0; firstPos = 0; step = 0; whRRatio = 0.0; whLRatio = 0.0; } PaperConfig::~PaperConfig() { } static double max3(double a, double b, double c) { if (a >= b && a >= c) return a; if (b >= a && b >= c) return b; return c; } static double min3(double a, double b, double c) { if (a <= b && a <= c) return a; if (b <= a && b <= c) return b; return c; } ImgLocateDryChemistry::ImgLocateDryChemistry() { initPaperConfig(); } ImgLocateDryChemistry::~ImgLocateDryChemistry() { } void ImgLocateDryChemistry::initPaperConfig() { PaperConfig* pc = new PaperConfig(); pc->itemsNum = 14; pc->paperSpatialType = PST_14_S; pc->slicesNum = 50;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 21.3;//定位块中心点的距离/试纸高度 pc->whRRatio = 2;//10毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_14_S, pc)); pc = new PaperConfig(); pc->itemsNum = 14; pc->paperSpatialType = PST_14_L; pc->slicesNum = 50;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 21.8;//定位块中心点的距离/试纸高度 pc->whRRatio = 3;//15毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_14_L, pc)); //---------------------------------- pc = new PaperConfig(); pc->paperSpatialType = PST_11_L; pc->itemsNum = 11; pc->slicesNum = 39;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 17.6;//定位块中心点的距离/试纸高度 pc->whRRatio = 3;//10毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_11_L, pc)); pc = new PaperConfig(); pc->paperSpatialType = PST_10_S; pc->itemsNum = 10; pc->slicesNum = 36;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 15.7;//定位块中心点的距离/试纸高度 pc->whRRatio = 2;//10毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_10_S, pc)); //---------------------------------- pc = new PaperConfig(); pc->paperSpatialType = PST_8_S; pc->itemsNum = 8; pc->slicesNum = 29;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 12.9;//定位块中心点的距离/试纸高度 pc->whRRatio = 2;//10毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_8_S, pc)); pc = new PaperConfig(); pc->paperSpatialType = PST_8_L; pc->itemsNum = 8; pc->slicesNum = 29;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 13.4;//定位块中心点的距离/试纸高度 pc->whRRatio = 3;//15毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_8_L, pc)); //---------------------------------- pc = new PaperConfig(); pc->paperSpatialType = PST_6_S; pc->itemsNum = 6; pc->slicesNum = 22;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 10.1;//定位块中心点的距离/试纸高度 pc->whRRatio = 2;//10毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_6_S, pc)); pc = new PaperConfig(); pc->paperSpatialType = PST_6_L; pc->itemsNum = 6; pc->slicesNum = 22;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 10.6;//定位块中心点的距离/试纸高度 pc->whRRatio = 3;//15毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_6_L, pc)); //---------------------------------- pc = new PaperConfig(); pc->paperSpatialType = PST_4_S; pc->itemsNum = 4; pc->slicesNum = 15;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 7.3;//定位块中心点的距离/试纸高度 pc->whRRatio = 2;//10毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_4_S, pc)); pc = new PaperConfig(); pc->paperSpatialType = PST_4_L; pc->itemsNum = 4; pc->slicesNum = 15;//最小分割单位 pc->firstPos = 2.25; pc->step = 3.5; pc->distTimes = 7.8;//定位块中心点的距离/试纸高度 pc->whRRatio = 3;//15毫米宽/5毫米高 pc->whLRatio = 0.6;//3毫米宽/5毫米高 mapPaperConfig.insert(std::make_pair(PST_4_L, pc)); // PaperConfig* configGreen = new PaperConfig(); // configGreen->color = ColorGreen; // configGreen->itemsNum = 15; // configGreen->slicesNum = 46;//最小分割单位 // configGreen->firstPos = 2;//第一点的步长 // configGreen->step = 3;//步长 × 最小分割长度(总距离/最小分割单位) // configGreen->distTimes = 20.7;//中心点的距离 除以 试纸的高度之比值 // configGreen->whRRatio = 2;//10毫米宽/5毫米高 // configGreen->whLRatio = 0.6;//3毫米宽/5毫米高 // mapPaperConfig.insert(std::make_pair(ColorGreen, configGreen)); } Mat& ImgLocateDryChemistry::GetPosition(Mat& s, cv::Rect& roi, bool bDraw, cv::Scalar& wbAvgRgb, vector&roiPositions) { assert(!s.empty()); s.copyTo(src); Mat(src, roi).copyTo(roiSrc); cv::cvtColor(roiSrc, rgb, COLOR_RGBA2RGB);//rgba---->>rgb //COLOR_RGBA2RGB = COLOR_BGRA2BGR, medianBlur(rgb, rgb, 5); vector mats; cv::split(rgb, mats); Mat blue = mats[0]; cv::cvtColor(rgb, hsv, COLOR_BGR2HSV);//bgr---->>hsv vector ml; split(hsv, ml); Mat& matV = ml[2]; Mat& matS = ml[1]; processImage(matS, blue, matV, roi, true, bDraw, wbAvgRgb, roiPositions); rectangle(src, cv::Point(roi.x, roi.y), cv::Point(roi.x + roi.width, roi.y + roi.height), cv::Scalar(0, 255, 0, 255), 2);// 画ROI if (recode == 0) { if (bDraw) { for (int i = 0; isecond) > 0){ ContourSelector::PairTExtend pt; pt.first = it->first; pt.second = it->second; vecPt3.push_back(pt); } // ContourGfExtend *pContourGf = it->second; // std::map< int, PaperConfig* >::iterator iter = mapPaperConfig.find(readLocatorColor(pContourGf)); // if (iter != mapPaperConfig.end()) // { // ContourSelector::PairTExtend pt; // pt.first = it->first; // pt.second = it->second; // vecPt3.push_back(pt); // } } if (vecPt3.size() < 2) { return LCC_UNKNOWN; } /* ContourSelector::VectorPT vecPt4; sort(vecPt3.begin(), vecPt3.end(), Comparer()); double maxH = vecPt3[0].second->getSize().height; cs.SelectContour(vecPt3, vecPt4, maxH*0.725, maxH*1.0, Height); if (vecPt4.size()<2) { vecPt4.clear(); sort(vecPt3.begin(), vecPt3.end(), Comparer()); double maxW = vecPt3[0].second->getSize().width; cs.SelectContour(vecPt3, vecPt4, maxW*0.725, maxW*1.0, Width); if (vecPt4.size()<2) return ColorUnknown; } */ ContourSelector::VectorPT vecPt4; sort(vecPt3.begin(), vecPt3.end(), Comparer()); double maxArea = vecPt3[0].second->getContourArea(); cs.SelectContour(vecPt3, vecPt4, maxArea*0.12, maxArea*1.05, Area); // cs.SelectContour(vecPt3, vecPt4, maxArea*0.15, maxArea*1.05, Area); if (vecPt4.size()<2) { return LCC_UNKNOWN; } // ContourSelector::VectorPT::iterator itr = vecPt4.begin(); // vector > bulidContours; // bulidContours.clear(); ContourSelector::VectorPT::iterator iter = vecPt4.begin(); vector centerPtVec; for (; iter != vecPt4.end(); ++iter) { ContourGfExtend *pContourGf = iter->second; cv::Point p= pContourGf->getContourCenter(); centerPtVec.push_back(p); } Vec4f line; fitLine(centerPtVec, line, DIST_L2, 0, 0.01, 0.01);//CV_DIST_L2为最简单快速的最小二乘法,推荐使用 double s = abs(line[1] / (line[0] + 0.000001)); slope = s; //if(s < 5 && s > 0.2) if(s > 0.2) {//斜率大于5说明,角度约在75~105之间吧 return LCC_UNKNOWN; } sort(vecPt4.begin(), vecPt4.end(), Comparer()); lRectContour = vecPt4.at(0); rRectContour = vecPt4.at(vecPt4.size() - 1); lRotRect = lRectContour.second->getRotatedRect();//save it rRotRect = rRectContour.second->getRotatedRect(); //save it int lColor = readLocatorColor(lRectContour.second); int rColor = readLocatorColor(rRectContour.second); if (lColor != rColor || lColor == LCC_UNKNOWN) { return LCC_UNKNOWN; } locatorColor = lColor; int x2 = (rRotRect.center.x - lRotRect.center.x) * (rRotRect.center.x - lRotRect.center.x); int y2 = (rRotRect.center.y - lRotRect.center.y) * (rRotRect.center.y - lRotRect.center.y); totalDist = sqrt(x2 + y2);//distance between two locators. // int lh = min(lRotRect.size.width, lRotRect.size.height); // int rh = min(rRotRect.size.width, rRotRect.size.height); int h = lRectContour.second->getContourArea() > rRectContour.second->getContourArea() ? min(lRotRect.size.width, lRotRect.size.height) : min(rRotRect.size.width, rRotRect.size.height); distTimes = totalDist / (h + 0.001); // distTimes = totalDist / (max(lh, rh) + 0.001); double areaTimes = lRectContour.second->getContourArea() > rRectContour.second->getContourArea() ? (lRectContour.second->getContourArea() + 0.01) / (rRectContour.second->getContourArea() + 0.01) : (rRectContour.second->getContourArea() + 0.01) / (lRectContour.second->getContourArea() + 0.01); // return verifyPaperConfig(totalDist, areaTimes); return verifyPaperConfig(distTimes, areaTimes); // paperConfig = mapPaperConfig.at(locatorColor); // return locatorColor; } int ImgLocateDryChemistry::verifyPaperConfig(double distRadio, double areaRadio) { //rules for areaRadio //3*5 / 10 * 5 --> 3.3 //3*3 / 15 * 5 --> 5 //so L --> 4 < areaRadio <6 double Max_AreaRadio_L = 6.0; double Min_AreaRadio_L = 4.0; //so S --> 2.5 < areaRadio < 4 double Max_AreaRadio_S = 4.0; double Min_AreaRadio_S = 2.5; //rules for distRadio //14 items: 21.3 / 21.8 --> 21.3 * 0.9 == 19.17 < XXX < 21.8 * 1.1 = 23.98 double Max_DistRadio_14 = 23.5; double Mix_DistRadio_14 = 19.5; //14L 21.8 double Max_DistRadio_14L = 23.98; double Mix_DistRadio_14L = 19.5; //11L items: 17.6 --> 17.6 * 0.9 == 15.84 < XXX < 17.6 *1.1 == 19.36 double Max_DistRadio_11 = 19.2; double Mix_DistRadio_11 = 15.9; //10S items: 15.7 --> 15.7 * 0.9 == 14.13 < XXX < 15.7 *1.1 == 17.27 double Max_DistRadio_10 = 17.2; double Mix_DistRadio_10 = 14.6; //8S items: 12.9 double Max_DistRadio_8 = 14.1; double Mix_DistRadio_8 = 11.6; //8L items: 13.4 double Max_DistRadio_8L = 14.5; double Mix_DistRadio_8L = 12; //6S items: 10.1 double Max_DistRadio_6 = 11.2; double Mix_DistRadio_6 = 9; //6L items: 10.6 double Max_DistRadio_6L = 11.4; double Mix_DistRadio_6L = 9.2; //4S items: 7.3 double Max_DistRadio_4 = 8.2; double Mix_DistRadio_4 = 6.6; //4L items: 7.8 double Max_DistRadio_4L = 8.5; double Mix_DistRadio_4L = 6.6; if(areaRadio < Min_AreaRadio_S || areaRadio > Max_AreaRadio_L){ return LCC_UNKNOWN; } if(areaRadio < Max_AreaRadio_S){// this is 10mm and 3mm //small paper if(distRadio > Mix_DistRadio_14 && distRadio < Max_DistRadio_14){ //14 paperSpatialType = PST_14_S; paperConfig = mapPaperConfig.at(PST_14_S); }else if(distRadio > Mix_DistRadio_10 && distRadio < Max_DistRadio_10){ //10 paperSpatialType = PST_10_S; paperConfig = mapPaperConfig.at(PST_10_S); } else if(distRadio > Mix_DistRadio_8 && distRadio < Max_DistRadio_8){ paperSpatialType = PST_8_S; paperConfig = mapPaperConfig.at(PST_8_S); } else if(distRadio > Mix_DistRadio_6 && distRadio < Max_DistRadio_6){ paperSpatialType = PST_6_S; paperConfig = mapPaperConfig.at(PST_6_S); } else if(distRadio > Mix_DistRadio_4 && distRadio < Max_DistRadio_4){ paperSpatialType = PST_4_S; paperConfig = mapPaperConfig.at(PST_4_S); } }else{//this is 15mm and 3mm if(distRadio > Mix_DistRadio_14L && distRadio < Max_DistRadio_14L){ //14 paperSpatialType = PST_14_L; paperConfig = mapPaperConfig.at(PST_14_L); } else if(distRadio > Mix_DistRadio_11 && distRadio < Max_DistRadio_11){ //11 paperSpatialType = PST_11_L; paperConfig = mapPaperConfig.at(PST_11_L); } else if(distRadio > Mix_DistRadio_8L && distRadio < Max_DistRadio_8L){ //11 paperSpatialType = PST_8_L; paperConfig = mapPaperConfig.at(PST_8_L); } else if(distRadio > Mix_DistRadio_6L && distRadio < Max_DistRadio_6L){ //11 paperSpatialType = PST_6_L; paperConfig = mapPaperConfig.at(PST_6_L); } else if(distRadio > Mix_DistRadio_4L && distRadio < Max_DistRadio_4L){ //11 paperSpatialType = PST_4_L; paperConfig = mapPaperConfig.at(PST_4_L); } } return locatorColor; } //bool ImgLocateDryChemistry::verifyDistance() //{ // int x2 = (rRotRect.center.x - lRotRect.center.x)*(rRotRect.center.x - lRotRect.center.x); // int y2 = (rRotRect.center.y - lRotRect.center.y)*(rRotRect.center.y - lRotRect.center.y); // totalDist = sqrt(x2 + y2);//distance between two locators. // int lh = min(lRotRect.size.width, lRotRect.size.height); // int rh = min(rRotRect.size.width, rRotRect.size.height); // //line(src, rRotRect.center, lRotRect.center, cv::Scalar(0, 0, 255, 255), 3); // if (abs(totalDist - paperConfig->distTimes * max(lh, rh)) > max(lh, rh) * 3.3 )//类似梯形失真 4 --> 3.3 // { // return false; // } // return true; //} Mat& ImgLocateDryChemistry::warpAffineImg(Mat &img) { double rotAngle = 0.0; if (lRectContour.second->getContourArea() > rRectContour.second->getContourArea()) rotAngle = lRotRect.angle; else rotAngle = rRotRect.angle; //double rotAngle = realBigAngle; if (rotAngle < -45) rotAngle += 90.0; cv::Point autoRoiCenter(img.cols * 0.5, img.rows * 0.5); Mat waMat = getRotationMatrix2D(autoRoiCenter, rotAngle, 1); Mat affineMat; warpAffine(img, affineMat, waMat, img.size(), INTER_LINEAR); waMat.release(); affineMat.copyTo(img); return img; } bool ImgLocateDryChemistry::analyseDefinition(Mat& sImg, cv::Rect& roi) { cv::Point2f lPts[4]; cv::Point2f rPts[4]; int lRectArea = lRectContour.second->getContourArea(); int rRectArea = rRectContour.second->getContourArea(); lRotRect.points(lPts); rRotRect.points(rPts); cv::Size lRectSize = lRotRect.size; cv::Size rRectSize = rRotRect.size; cv::Rect rcBigCross; cv::Rect rcSideEdge; cv::Rect rcSmallSideEdge; if (lRectArea>rRectArea) { bRot = true;//放反,左边定位块面积大于右边。即:左大右小 lRotRectWidth = max(lRectSize.width, lRectSize.height); lRotRectHeight = min(lRectSize.width, lRectSize.height); if (paperConfig->whLRatio >= 1) { rRotRectWidth = max(rRectSize.width, rRectSize.height); rRotRectHeight = min(rRectSize.width, rRectSize.height); } else { rRotRectWidth = min(rRectSize.width, rRectSize.height); rRotRectHeight = max(rRectSize.width, rRectSize.height); } double whLRatio = (double)lRotRectWidth / lRotRectHeight; double whRRatio = (double)rRotRectWidth / rRotRectHeight; if ((abs(whLRatio - paperConfig->whRRatio) / paperConfig->whRRatio) > 0.2 || (abs(whRRatio - paperConfig->whLRatio) / paperConfig->whLRatio) > 0.25) { return false; } rcBigCross.x = lRotRect.center.x - lRotRectWidth * 0.25; rcBigCross.y = lRotRect.center.y - lRotRectHeight; rcBigCross.width = lRotRectWidth * 0.5; rcBigCross.height = lRotRectHeight * 2; rcSideEdge.x = lRotRect.center.x - lRotRectWidth*0.75; rcSideEdge.y = lRotRect.center.y - lRotRectHeight*0.25; rcSideEdge.width = lRotRectWidth * 0.5; rcSideEdge.height = lRotRectHeight * 0.5; rcSmallSideEdge.x = rRotRect.center.x;// -rRotRectWidth*0.75; rcSmallSideEdge.y = rRotRect.center.y - rRotRectHeight*0.25; rcSmallSideEdge.width = rRotRectHeight * 0.5; rcSmallSideEdge.height = rRotRectHeight * 0.5; } else { bRot = false; //即:左小右大 if (paperConfig->whLRatio >= 1) { lRotRectWidth = max(lRectSize.width, lRectSize.height); lRotRectHeight = min(lRectSize.width, lRectSize.height); } else { lRotRectWidth = min(lRectSize.width, lRectSize.height); lRotRectHeight = max(lRectSize.width, lRectSize.height); } rRotRectWidth = max(rRectSize.width, rRectSize.height); rRotRectHeight = min(rRectSize.width, rRectSize.height); double whLRatio = (double)lRotRectWidth / lRotRectHeight; double whRRatio = (double)rRotRectWidth / rRotRectHeight; if ((abs(whLRatio - paperConfig->whLRatio) / paperConfig->whLRatio) > 0.25 || (abs(whRRatio - paperConfig->whRRatio) / paperConfig->whRRatio) > 0.2) { return false; } rcBigCross.x = rRotRect.center.x - rRotRectWidth * 0.25; rcBigCross.y = rRotRect.center.y - rRotRectHeight; rcBigCross.width = rRotRectWidth * 0.5; rcBigCross.height = rRotRectHeight * 2; rcSideEdge.x = rRotRect.center.x + rRotRectWidth*0.25; rcSideEdge.y = rRotRect.center.y - rRotRectHeight*0.25; rcSideEdge.width = rRotRectWidth * 0.5; rcSideEdge.height = rRotRectHeight * 0.5; rcSmallSideEdge.x = lRotRect.center.x - lRotRectHeight*0.5; rcSmallSideEdge.y = lRotRect.center.y - lRotRectHeight*0.25; rcSmallSideEdge.width = lRotRectHeight * 0.5; rcSmallSideEdge.height = lRotRectHeight * 0.5; } //判断高度比,比例为1 if (abs((double)lRotRectHeight / rRotRectHeight - 1) > 0.18//梯形失真 || lRotRectHeight < 15 || rRotRectHeight < 15 || rcBigCross.x <= 0 || rcBigCross.y <= 0 || rcBigCross.x + rcBigCross.width >= (roi.width - 1) || rcBigCross.y + rcBigCross.height >= (roi.height - 1) || rcSmallSideEdge.x <= 0 || rcSmallSideEdge.y <= 0 || rcSmallSideEdge.x + rcSmallSideEdge.width >= (roi.width - 1) || rcSmallSideEdge.y + rcSmallSideEdge.height >= (roi.height - 1) || rcSideEdge.x <= 0 || rcSideEdge.y <= 0 || rcSideEdge.x + rcSideEdge.width >= (roi.width - 1) || rcSideEdge.y + rcSideEdge.height >= (roi.height - 1)) { return false; } rcBigCross.x += roi.x; rcBigCross.y += roi.y; rcSideEdge.x += roi.x; rcSideEdge.y += roi.y; rcSmallSideEdge.x += roi.x; rcSmallSideEdge.y += roi.y; Mat m1(src, rcBigCross); Mat m2 = Mat(src, rcSideEdge).t(); Mat m3; Mat m4; Mat m6; cv::cvtColor(m1, m3, COLOR_BGR2GRAY); cv::cvtColor(m2, m4, COLOR_BGR2GRAY); Mat m5 = Mat(src, rcSmallSideEdge).t(); cv::cvtColor(m5, m6, COLOR_BGR2GRAY); // rectangle(src, rcBigCross, cv::Scalar(0, 0, 255, 255), 2); // rectangle(src, rcSideEdge, cv::Scalar(0, 0, 255, 255), 2); // rectangle(src, rcSmallSideEdge, cv::Scalar(0, 0, 255, 255), 2); //easy to scan // if(calGrayImgDefinition(m3,3.5,4)==true && calGrayImgDefinition(m4,2.5,2)==true && calGrayImgDefinition(m6,2,2)==true) // return true; if(calGrayImgDefinition(m3, 4, 5) && calGrayImgDefinition(m4, 3, 2)) return true; // if(locatorColor==ColorRed || locatorColor == ColorOrange || locatorColor==ColorBlue_14) // { // if(calGrayImgDefinition(m3, 2.5, 4) && calGrayImgDefinition(m4, 2, 2) && // calGrayImgDefinition(m6, 2, 1)) // return true; // }/*else if(locatorColor==ColorBlue_14){ // if(calGrayImgDefinition(m3,3.7,5)==true && calGrayImgDefinition(m4,2.8,2)==true && calGrayImgDefinition(m6,2.3,2)==true) // return true; // }*/else{ // if(calGrayImgDefinition(m3, 4, 5) && calGrayImgDefinition(m4, 3, 2)) // return true; // } return false; // // Mat bigCrossMat(sImg, rcBigCross); // Mat sideEdgeMat = Mat(sImg, rcSideEdge).t(); // Mat smallsideEdgeMat = Mat(sImg, rcSmallSideEdge).t(); ///* // rcBigCross.x += roi.x; rcBigCross.y += roi.y; // rcSideEdge.x += roi.x; rcSideEdge.y += roi.y; // rcSmallSideEdge.x += roi.x; rcSmallSideEdge.y += roi.y; // rectangle(src, rcBigCross, cv::Scalar(0, 255, 0, 255), 1); // rectangle(src, rcSideEdge, cv::Scalar(0, 255, 0, 255), 1); // rectangle(src, rcSmallSideEdge, cv::Scalar(0, 255, 0, 255), 1); //*/ // double diff, avg, diffC, diffBS, diffSS, avgC, avgBS, avgSS; // int low, top, lowC, lowBS, lowSS, topC, topBS, topSS; // double crossDefinitionValue, sideDefinitionValue, definitionValueSmall; // crossDefinitionValue = calImgDefinition(bigCrossMat, diffC, avgC, lowC, topC); // sideDefinitionValue = calImgDefinition(sideEdgeMat, diffBS, avgBS, lowBS, topBS); // definitionValueSmall = calImgDefinition(smallsideEdgeMat, diffSS, avgSS, lowSS, topSS); // // topDefinitionValue = max3(crossDefinitionValue, sideDefinitionValue, definitionValueSmall); // diff = max3(diffC, diffBS, diffSS); // avg = min3(avgC, avgBS, avgSS);//下界 // low = min3(lowC, lowBS, lowSS);//下界 // top = max3(topC, topBS, topSS);//上界 // //cout < 15 || top < 2){ // // //if (diff < 85 || definitionValue < 1.85 || avg > 40 || low > 15 || top < 2) { // return false; // } // return true; } bool ImgLocateDryChemistry::calGrayImgDefinition(Mat &img,double m,int u) { Mat sobelX,sobelY, absSum; cv::Scalar scalar; Scharr(img, sobelX,CV_16S, 1, 0, 1, 0, cv::BORDER_DEFAULT);//Sobel cv::convertScaleAbs(sobelX, sobelX); Scharr(img, sobelY,CV_16S, 0, 1, 1, 0, cv::BORDER_DEFAULT);//Sobel cv::convertScaleAbs(sobelY, sobelY); cv::addWeighted(sobelX, 0.1, sobelY, 0.9, 0, absSum); Scalar Sum = cv::sum(absSum); double avg = Sum.val[0] / (absSum.rows * absSum.cols); double diff; int low,up; uchar *pData = absSum.data; double multiple,val,pre; int step = absSum.step; bool first = true; multiple= val= pre=diff = 0; low = up=0; for (int y = 0; y < absSum.rows; ++y) { for (int x = 0; x < absSum.cols; ++x) { val += pData[y * step + x]; } val = val / absSum.cols; if (first) { pre = val + 0.00001; first = false; continue; } // if (val > avg) low++;//60,大于均值的行数 if (val > 180) up++;//大值的行数,200已经非常好的梯度 if (abs(val - pre) > diff) { multiple = max(val, pre) / (min(val, pre) + 0.0001); diff = abs(val - pre); } pre = val; } if(multiple > m && up > u) return true; return false; } double ImgLocateDryChemistry::calImgDefinition(Mat &img, double &diff, double &avg, int &lowLines, int &upLines) { Mat sobelX,sobelY, absSum; cv::Scalar scalar; Scharr(img, sobelX, CV_16S, 1, 0);//Sobel Scharr(img, sobelY, CV_16S, 0, 1);//Sobel absdiff(sobelX, scalar, sobelX);//abs负值变正值 absdiff(sobelY, scalar, sobelY);//abs负值变正值 add(sobelX, sobelY, absSum); absSum.convertTo(absSum, CV_8UC1, 0.25); Scalar Sum = cv::sum(absSum); avg = Sum.val[0] / (absSum.rows * absSum.cols + 0.001); uchar *pData = absSum.data; double multiple,val,pre; int step = absSum.step; multiple= val= pre=diff = lowLines = upLines=0; for (int y = 0; y < absSum.rows; ++y) { for (int x = 0; x < absSum.cols; ++x) { val += pData[y * step + x]; } val = val / absSum.cols; if (pre == 0 || val < 10) { pre = val + 0.00001; continue; } if (val > avg) lowLines++;//60,大于均值的行数 if (val > 185) upLines++;//大值的行数,200已经非常好的梯度 if (abs(val - pre) > diff) { multiple = max(val, pre) / (min(val, pre) + 0.0001); diff = abs(val - pre); } pre = val; } return multiple; } int ImgLocateDryChemistry::readLocatorColor(ContourGfExtend* pContourGfE) { /* Point pt = pContourGfE->getContourCenter(); if(pt.x < 6 || (pt.x + 10) > src.cols || pt.y < 6 || (pt.y + 10) > src.rows) return ColorUnknown; Rect rc(pt.x - 5, pt.y - 5, 10, 10); Mat rcMat(src, rc); Mat hMat, labMat; cvtColor(rcMat, hMat, COLOR_BGR2HSV); Scalar avgHsv = mean(hMat); double h = avgHsv[0]; if(h < 10 || h > 165) return ColorRed; if(h > 100 && h < 140) return ColorBlue; if(h > 50 && h < 90) return ColorGreen;*/ double r = pContourGfE->getColorPercentage(0); double g = pContourGfE->getColorPercentage(1); double b = pContourGfE->getColorPercentage(2); if (g > b && g > r) return LCC_GREEN; if (r > g && r > b) return LCC_RED; if (b > r && b > g) return LCC_BLUE; Point pt = pContourGfE->getContourCenter(); if (pt.x < 10 || pt.y < 10 || (pt.x+10) > rgb.cols || (pt.y+10) > rgb.rows) return LCC_UNKNOWN; cv::Rect rect(pt.x - 5, pt.y - 5, 10, 10); Mat mat(hsv, rect); Scalar mv, dv; meanStdDev(mat, mv, dv); double h = mv[0]; if (h < 25 || h > 150) { return LCC_RED; } else if (h >40 && h < 95) { return LCC_GREEN; } else if (h >100 && h < 135) { return LCC_BLUE; } if (r<0.225&&b>0.1) { double t = g / (b + 0.00001); if (t >= 0.85&&t <= 1.0) { return LCC_GREEN; } } return LCC_UNKNOWN; } void ImgLocateDryChemistry::releaseContoursGf(ContourSelector::VectorPT& vectorPt, int code) { for (int i = 0; iitemsNum; } return 0; } int ImgLocateDryChemistry::GetLocatorType() { if(paperConfig != nullptr){ if(paperConfig->whRRatio > 2) return 3; else return 2; } return 0; } void ImgLocateDryChemistry::savePaperImg() { Point2f pts1[4]; rRotRect.points(pts1); Point2f pts2[4]; lRotRect.points(pts2); vector points; for (int i = 0; i < 4; i++) { points.insert(points.begin(), pts1[i]); points.insert(points.begin(), pts2[i]); } Rect maxRect = boundingRect(points); if (maxRect.x < 1) maxRect.x = 1; if (maxRect.y < 1) maxRect.y = 1; if ((maxRect.width + maxRect.x) >= rgb.cols) { maxRect.width = rgb.cols - maxRect.x; } if ((maxRect.height + maxRect.y) >= rgb.rows) { maxRect.height = rgb.rows - maxRect.y; } paperImg.release(); if ((maxRect.width + maxRect.x) <= rgb.cols && (maxRect.height + maxRect.y) <= rgb.rows) { Mat(rgb, maxRect).copyTo(paperImg);//roiSrc } else { rgb.copyTo(paperImg);//roiSrc } cvtColor(paperImg, paperImg, COLOR_BGRA2RGB); } int ImgLocateDryChemistry::processImage(Mat& sImg, Mat& b, Mat&v, cv::Rect& roi, bool useSThres, bool bDraw, cv::Scalar& wbAvgRgb, vector&roiPositions) { recode = 0; double s = 0; paperSpatialType = PST_UNKNOWN; int c = analyseLocatorColor(sImg, s); //ColorUnknown if (c == LCC_UNKNOWN || paperSpatialType == PST_UNKNOWN) { /* if (s > 5) return (recode = 9);*/ return ( recode = 1 ); } // if (false == verifyDistance()) // { // return (recode = 2); // } sImg = warpAffineImg(sImg); if (false == analyseDefinition(sImg, roi)) { return (recode = 4); } //开始计算各个反应快的具体位置 paperHeight = (lRotRectHeight + rRotRectHeight)*0.5; int dx = rRotRect.center.x - lRotRect.center.x;//dx一定大于0 int dy = rRotRect.center.y - lRotRect.center.y;//dy可能大于0,小于0,等于0 double dx2 = dx*dx; double dy2 = dy*dy; double sinVal = sqrt(dy2 / (dx2 + dy2)); double cosVal = sqrt(1 - (dy2 / (dx2 + dy2))); int leftRotRectHalfWidth = lRotRectWidth*0.5; int rightRotRectHalfWidth = rRotRectWidth*0.5; cv::Point leftEdgeCenter; cv::Point rightEdgeCenter; int absDy = abs(dy); double k = 0.0; if (absDy >= 0 && absDy <= 2) {//左右定位块的高度差在2像素范围之内,我们认为图像摆的很正,不需要调整 leftEdgeCenter.x = lRotRect.center.x + leftRotRectHalfWidth; leftEdgeCenter.y = lRotRect.center.y; rightEdgeCenter.x = rRotRect.center.x - rightRotRectHalfWidth; rightEdgeCenter.y = rRotRect.center.y; k = 0.0; } else if (absDy>2) { k = (double)dy / dx;//K值实际上是三角函数的Tan函数,对边 除以 临边 if (k<0) {//右低,左高 leftEdgeCenter.x = lRotRect.center.x + leftRotRectHalfWidth*cosVal; leftEdgeCenter.y = lRotRect.center.y - leftRotRectHalfWidth*sinVal;//上移 rightEdgeCenter.x = rRotRect.center.x - rightRotRectHalfWidth*cosVal; rightEdgeCenter.y = rRotRect.center.y + rightRotRectHalfWidth*sinVal;//下移 } else if (k>0) {//右高,左低 leftEdgeCenter.x = lRotRect.center.x + leftRotRectHalfWidth*cosVal; leftEdgeCenter.y = lRotRect.center.y + leftRotRectHalfWidth*sinVal; rightEdgeCenter.x = rRotRect.center.x - rightRotRectHalfWidth*cosVal; rightEdgeCenter.y = rRotRect.center.y - rightRotRectHalfWidth*sinVal; } } avgDist = (double)(rightEdgeCenter.x - leftEdgeCenter.x) / paperConfig->slicesNum; roiPositions.clear(); double firstPointDistance = avgDist * paperConfig->firstPos; double stepDistance = avgDist * paperConfig->step; cv::Point firstPt(leftEdgeCenter.x + firstPointDistance, leftEdgeCenter.y + k*firstPointDistance);//第一个块位置 roiPositions.push_back(firstPt); double tmp = 0; for (int i = 1; i < paperConfig->itemsNum; ++i) { cv::Point p; tmp += stepDistance; p.x = (int)(firstPt.x + tmp); p.y = (int)(firstPt.y + k*tmp); roiPositions.push_back(p); } //计算白色块位置 cv::Point wbPt;//白平衡位置 int wbDist = firstPointDistance*3.1; if (bRot) { wbPt.x = leftEdgeCenter.x - wbDist; wbPt.y = leftEdgeCenter.y - k*wbDist; } else { wbPt.x = rightEdgeCenter.x + wbDist; wbPt.y = rightEdgeCenter.y + k*wbDist; } cv::Rect wbRc((int)wbPt.x - 5, (int)wbPt.y - 5, 10, 10); if (wbRc.x <= 0 || (wbRc.x + wbRc.width) >= (roi.width - 1) || wbRc.y <= 0 || (wbRc.y + wbRc.height) >= (roi.height - 1)) { return (recode = 4); } Mat wbImg(rgb, wbRc);//roiSrc wbAvgRgb = mean(wbImg); if (bRot)//旋转 { vector cpyRoiPositions(roiPositions); roiPositions.clear(); for (int i = cpyRoiPositions.size() - 1; i >= 0; --i) { roiPositions.push_back(cpyRoiPositions[i]); } } roiPositions.push_back(wbPt); score = 100; savePaperImg(); return (recode = 0); }