d6aeede2bc
从桌面工程复制而来,作为本仓库的 Xuxucheck/ 子目录。 为控制仓库体积做了两处删减: - 移除 Frameworks/opencv2.xcframework 下的两个 visionOS 切片 (xros-arm64、xros-arm64-simulator,合计约 106 MB),并同步删掉该 xcframework 内 Info.plist 里对应的两条 AvailableLibraries 记录, 只保留 ios-arm64 与 ios-arm64_x86_64-simulator。 - 移除全部 .DS_Store 与 xcuserdata/。 已用 xcodebuild 从本目录完整编译验证:BUILD SUCCEEDED, ProcessXCFramework 以 --platform ios 成功选中框架,产物含 3699 个 cv:: 符号 (OpenCV 确实链入),嵌入 framework 3 个,与移除无用 pod 之后的状态一致。 仓库约 206 MB,其中 OpenCV 203 MB、其余源码与依赖约 3 MB。
1040 lines
34 KiB
C++
1040 lines
34 KiB
C++
//#include <opencv2/imgproc/types_c.h>
|
|
#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<cv::Point>&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<Mat> mats;
|
|
cv::split(rgb, mats);
|
|
Mat blue = mats[0];
|
|
cv::cvtColor(rgb, hsv, COLOR_BGR2HSV);//bgr---->>hsv
|
|
vector<Mat> 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; i<roiPositions.size() - 1; ++i)
|
|
{
|
|
circle(src, cv::Point(roiPositions[i].x + roi.x, roiPositions[i].y + roi.y), (int)(avgDist*0.5), cv::Scalar(0, 0, 255, 255), 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
releaseContoursGf(vecPt);
|
|
|
|
return src;
|
|
}
|
|
|
|
int ImgLocateDryChemistry::analyseLocatorColor(Mat& sImg, double& slope)
|
|
{
|
|
Mat matT;
|
|
cv::threshold(sImg, matT, 128, 255, THRESH_BINARY | THRESH_OTSU);
|
|
//cv::erode(matT, matT, Mat(), Point(), 2); //cv::dilate(matT, matT, Mat(), Point(), 2);
|
|
morphologyEx(matT, matT, MORPH_OPEN, cv::getStructuringElement(MORPH_RECT, cv::Size(9,9)));
|
|
ContourSelector::ContoursTExtend contours;
|
|
ContourSelector::HierarchyTExtend hierarchy;
|
|
findContours(matT, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
|
|
for (int i = 0; i<vecPt.size(); ++i)
|
|
{
|
|
delete vecPt[i].second;
|
|
vecPt[i].second = NULL;
|
|
}
|
|
vecPt.clear();
|
|
cs.CalContoursGf(rgb, contours, vecPt);
|
|
if (vecPt.size() < 2)
|
|
{
|
|
return LCC_UNKNOWN;
|
|
}
|
|
//
|
|
// drawContours(src, contours, -1, Scalar(255, 0, 255));
|
|
|
|
ContourSelector::VectorPT vecPt0_0;
|
|
cs.SelectContour(vecPt, vecPt0_0, sImg.cols * 0.05, sImg.cols * 0.95,RightBottomX);
|
|
ContourSelector::VectorPT vecPt0_1;
|
|
cs.SelectContour(vecPt0_0, vecPt0_1, sImg.cols * 0.05, sImg.cols * 0.95, LeftTopX);
|
|
|
|
ContourSelector::VectorPT vecPt0;
|
|
cs.SelectContour(vecPt0_1, vecPt0, 150/*10X20*/, 100000/*200X400*/, Area);
|
|
//cs.SelectContour(vecPt, vecPt0, 150/*10X20*/, 100000/*200X400*/, Area);
|
|
if (vecPt0.size()<2)
|
|
{
|
|
return LCC_UNKNOWN;
|
|
}
|
|
ContourSelector::VectorPT vecPt1;
|
|
cs.SelectContour(vecPt0, vecPt1, 0.25, 0.75, AspectRatio);// 3/5, 5/10, 5/15, 5/5
|
|
if (vecPt1.size()<2)
|
|
{
|
|
return LCC_UNKNOWN;
|
|
}
|
|
ContourSelector::VectorPT vecPt2;
|
|
cs.SelectContour(vecPt1, vecPt2, 0.85, 1.1, Rectangularity);
|
|
if (vecPt2.size()<2)
|
|
{
|
|
return LCC_UNKNOWN;
|
|
}
|
|
|
|
ContourSelector::VectorPT vecPt3;
|
|
ContourSelector::VectorPT::iterator it = vecPt2.begin();
|
|
for (; it != vecPt2.end(); ++it)
|
|
{
|
|
if(readLocatorColor(it->second) > 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<Height>());
|
|
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<Width>());
|
|
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<Area>());
|
|
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<vector<cv::Point> > bulidContours;
|
|
// bulidContours.clear();
|
|
|
|
ContourSelector::VectorPT::iterator iter = vecPt4.begin();
|
|
vector<Point> 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<CenterX, false>());
|
|
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 <<diff << " " << crossDefinitionValue << " " << avg << " " << low << " " << top << " " << sideDefinitionValue << " " << definitionValueSmall << endl;
|
|
// if(diff < 85 || topDefinitionValue < 1.85 || low > 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; i<vectorPt.size(); ++i)
|
|
{
|
|
delete vectorPt[i].second;
|
|
vectorPt[i].second = NULL;
|
|
}
|
|
vectorPt.clear();
|
|
|
|
}
|
|
|
|
int ImgLocateDryChemistry::GetPaperItems()
|
|
{
|
|
if(paperConfig != nullptr){
|
|
return paperConfig->itemsNum;
|
|
}
|
|
|
|
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<Point2f> 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<cv::Point>&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<cv::Point> 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);
|
|
} |