algoLib/sourceCode/YouJiang_sheetPositioning.cpp

422 lines
12 KiB
C++
Raw Normal View History

#include <vector>
#include "SG_baseDataType.h"
#include "SG_baseAlgo_Export.h"
#include "YouJiang_sheetPositioning_Export.h"
#include <opencv2/opencv.hpp>
#define DEBUG_OUT_IMAGE 1
std::string m_strVersion = "1.0.0";
const char* wd_sheetPositionVersion(void)
{
return m_strVersion.c_str();
}
//<2F><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD>Ͳο<CDB2><CEBF><EFBFBD>ƽƽ<C6BD><EFBFBD><E6A3AC><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ƽ
//<2F><>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƽ<EFBFBD><EFBFBD><E6B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>
SSG_planeCalibPara wd_sheetPosition_getBaseCalibPara(
std::vector< std::vector<SVzNL3DPosition>>& scanLines)
{
return sg_getPlaneCalibPara2(scanLines);
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̬<EFBFBD><CCAC>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void wd_sheetPosition_lineDataR(
std::vector< SVzNL3DPosition>& a_line,
const double* camPoseR,
double groundH)
{
lineDataRT_vector(a_line, camPoseR, groundH);
}
2026-03-10 16:57:56 +08:00
//<2F><>ȡ<EFBFBD><C8A1>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ı<EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void wd_computeClosedEdgeClusters(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
const SSG_planeCalibPara groundCalibPara,
const SWD_sheetAlgoParam algoParam,
int* errCode,
2026-03-10 16:57:56 +08:00
std::vector<std::vector< SVzNL2DPoint>>& clusters, //ֻ<><D6BB>¼λ<C2BC><CEBB>
std::vector<SVzNL3DRangeD>& clustersRoi3D)
{
int lineNum = (int)scanLines.size();
if (lineNum == 0)
{
*errCode = SG_ERR_3D_DATA_NULL;
return;
}
bool isGridData = true;
int linePtNum = (int)scanLines[0].size();
for (int i = 0; i < lineNum; i++)
2026-03-10 16:57:56 +08:00
{
if (linePtNum != (int)scanLines[i].size())
isGridData = false;//<2F>д<EFBFBD><D0B4><EFBFBD>
//<2F><>ƽ<EFBFBD><C6BD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
wd_sheetPosition_lineDataR(scanLines[i], groundCalibPara.planeCalib, -1);
}
if (false == isGridData)//<2F><><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
{
*errCode = SG_ERR_NOT_GRID_FORMAT;
return;
}
//<2F><>ȡ<EFBFBD><C8A1>Ƭ<EFBFBD>ϵ<EFBFBD>Բ<EFBFBD><D4B2>
//<2F><>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ
std::vector<std::vector<SSG_basicFeature1D>> lineJumpFeatures_v;
for (int line = 0; line < lineNum; line++)
{
if (line == 76)
int kkk = 1;
std::vector<SVzNL3DPosition>& lineData = scanLines[line];
if (linePtNum != (int)lineData.size())
isGridData = false;
//<2F>˲<EFBFBD><CBB2><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><ECB3A3>
sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], linePtNum, algoParam.filterParam);
std::vector<SSG_basicFeature1D> line_jumpFeatures;
int dataSize = (int)lineData.size();
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>Jumping<6E><67><EFBFBD><EFBFBD>
sg_getLineLJumpFeature_cornerMethod(
&lineData[0],
dataSize,
line,
algoParam.cornerParam,
true, //ȡ<><C8A1><EFBFBD><EFBFBD>
line_jumpFeatures);
lineJumpFeatures_v.push_back(line_jumpFeatures);
}
if (false == isGridData)//<2F><><EFBFBD>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
{
*errCode = SG_ERR_NOT_GRID_FORMAT;
return;
}
//<2F><><EFBFBD><EFBFBD>ˮƽɨ<C6BD><C9A8>
std::vector<std::vector<SVzNL3DPosition>> hLines_raw;
hLines_raw.resize(linePtNum);
for (int i = 0; i < linePtNum; i++)
hLines_raw[i].resize(lineNum);
for (int line = 0; line < lineNum; line++)
{
for (int j = 0; j < linePtNum; j++)
{
scanLines[line][j].nPointIdx = 0; //<2F><>ԭʼ<D4AD><CABC><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0<EFBFBD><30><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ʹ<EFBFBD>ã<EFBFBD>
hLines_raw[j][line] = scanLines[line][j];
hLines_raw[j][line].pt3D.x = scanLines[line][j].pt3D.y;
hLines_raw[j][line].pt3D.y = scanLines[line][j].pt3D.x;
}
}
//ˮƽjump<6D><70><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ
std::vector<std::vector<SSG_basicFeature1D>> lineJumpFeatures_h;
int lineNum_h_raw = (int)hLines_raw.size();
for (int line = 0; line < lineNum_h_raw; line++)
{
if (line == 522)
int kkk = 1;
std::vector<SVzNL3DPosition>& lineData = hLines_raw[line];
//<2F>˲<EFBFBD><CBB2><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><ECB3A3>
int ptNum = (int)lineData.size();
sg_lineDataRemoveOutlier_changeOriginData(&lineData[0], ptNum, algoParam.filterParam);
std::vector<SSG_basicFeature1D> line_jumpFeatures;
int dataSize = (int)lineData.size();
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>Jumping<6E><67><EFBFBD><EFBFBD>
sg_getLineLJumpFeature_cornerMethod(
&lineData[0],
dataSize,
line,
algoParam.cornerParam,
true, //ȡ<><C8A1><EFBFBD><EFBFBD>
line_jumpFeatures);
lineJumpFeatures_h.push_back(line_jumpFeatures);
}
//<2F><>ע
std::vector<std::vector<SSG_featureClusteringInfo>> featureInfoMask;
std::vector<std::vector<SVzNL3DPoint>> feature3DInfo;
featureInfoMask.resize(lineNum);
feature3DInfo.resize(lineNum);
for (int i = 0; i < lineNum; i++)
{
featureInfoMask[i].resize(lineNum_h_raw);
feature3DInfo[i].resize(lineNum_h_raw);
}
//<2F><>ֱ<EFBFBD><D6B1>ע
for (int line = 0; line < lineNum; line++)
{
if (line == 390)
int kkk = 1;
std::vector<SSG_basicFeature1D>& a_lineJumpFeature = lineJumpFeatures_v[line];
for (int m = 0, m_max = (int)a_lineJumpFeature.size(); m < m_max; m++)
{
int px = a_lineJumpFeature[m].jumpPos2D.x;
int py = a_lineJumpFeature[m].jumpPos2D.y;
SSG_featureClusteringInfo& a_featureInfo = featureInfoMask[px][py];
a_featureInfo.clusterID = 0;
a_featureInfo.featurType = 1;
a_featureInfo.featureIdx_v = m;
a_featureInfo.featureIdx_h = 0;
a_featureInfo.lineIdx = px;
a_featureInfo.ptIdx = py;
a_featureInfo.flag = 0;
SVzNL3DPoint& a_feature3D = feature3DInfo[px][py];
a_feature3D = a_lineJumpFeature[m].jumpPos;
scanLines[px][py].nPointIdx = 1;
}
}
//ˮƽ<CBAE><C6BD>ע
for (int line = 0; line < lineNum_h_raw; line++)
{
std::vector<SSG_basicFeature1D>& a_lineJumpFeature = lineJumpFeatures_h[line];
for (int m = 0, m_max = (int)a_lineJumpFeature.size(); m < m_max; m++)
{
int py = a_lineJumpFeature[m].jumpPos2D.x;
int px = a_lineJumpFeature[m].jumpPos2D.y;
SSG_featureClusteringInfo& a_featureInfo = featureInfoMask[px][py];
if (a_featureInfo.featurType == 0)
{
a_featureInfo.clusterID = 0;
a_featureInfo.lineIdx = px;
a_featureInfo.ptIdx = py;
a_featureInfo.flag = 0;
}
a_featureInfo.featurType += 2;
a_featureInfo.featureIdx_h = m;
SVzNL3DPoint& a_feature3DValue = feature3DInfo[px][py];
a_feature3DValue = { a_lineJumpFeature[m].jumpPos.y, a_lineJumpFeature[m].jumpPos.x, a_lineJumpFeature[m].jumpPos.z };
scanLines[px][py].nPointIdx += 2;
}
}
//<2F><><EFBFBD><EFBFBD>
//<2F><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>˼<EFBFBD><EFBFBD>ع<EFBFBD>˼·<CBBC><C2B7><EFBFBD>и<EFBFBD>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
int clusterID = 1;
int clusterCheckWin = 3;
for (int y = 0; y < lineNum_h_raw; y++)
{
for (int x = 0; x < lineNum; x++)
{
SSG_featureClusteringInfo& a_featureInfo = featureInfoMask[x][y];
if ((0 == a_featureInfo.featurType) || (a_featureInfo.clusterID > 0)) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD>
continue;
SVzNL3DPoint& a_feature3DValue = feature3DInfo[x][y];
SVzNL3DRangeD a_clusterRoi;
a_clusterRoi.xRange.min = a_feature3DValue.x;
a_clusterRoi.xRange.max = a_feature3DValue.x;
a_clusterRoi.yRange.min = a_feature3DValue.y;
a_clusterRoi.yRange.max = a_feature3DValue.y;
a_clusterRoi.zRange.min = a_feature3DValue.z;
a_clusterRoi.zRange.max = a_feature3DValue.z;
SVzNL2DPoint a_seedPos = { x, y };
std::vector< SVzNL2DPoint> a_cluster;
a_cluster.push_back(a_seedPos);
wd_gridPointClustering(
featureInfoMask,//int<6E><74><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD>clusterID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>flag
feature3DInfo,//double,<2C><>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
clusterCheckWin, //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
algoParam.growParam,//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
clusterID, //<2F><>ǰCluster<65><72>ID
a_cluster, //result
a_clusterRoi
);
clusters.push_back(a_cluster);
clustersRoi3D.push_back(a_clusterRoi);
clusterID++;
}
}
2026-03-10 16:57:56 +08:00
}
//<2F><>Ƭ<EFBFBD><C6AC>λ
//ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>ƥ<EFBFBD><EFBFBD><E4A3BA>1<EFBFBD><31><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD>䱡Ƭ
void wd_YouJiang_getSheetPosition(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
const SWD_sheetTemplateParam templateParam,
const SSG_planeCalibPara groundCalibPara,
const SWD_sheetAlgoParam algoParam,
SWD_gripState* opState, //<2F><><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ָʾ<D6B8><CABE>ǰ״̬
int* errCode,
std::vector<SWD_sheetGrasper>& resultObjPositions)
{
std::vector<std::vector< SVzNL2DPoint>> clusters;//ֻ<><D6BB>¼λ<C2BC><CEBB>
std::vector<SVzNL3DRangeD> clustersRoi3D;
//<2F><>ȡ<EFBFBD><C8A1>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ı<EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
wd_computeClosedEdgeClusters(
scanLines,
groundCalibPara,
algoParam,
errCode,
clusters, //ֻ<><D6BB>¼λ<C2BC><CEBB>
clustersRoi3D);
2026-03-10 16:57:56 +08:00
int clusterNum = (int)clusters.size();
//ͶӰ<CDB6>ͱ<EFBFBD>ע<EFBFBD><D7A2>ͶӰ<CDB6><D3B0>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3>ƥ<EFBFBD><C6A5>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1mmΪ<6D><CEAA>λ.<2E><>¼clusterID
SVzNL3DRangeD roi3D = sg_getScanDataROI_vector(scanLines);
double projectionScale = 1.0; //<2F><>1mmΪͶӰ<CDB6>߶<EFBFBD>
int projecction_xw = (int)((roi3D.xRange.max - roi3D.xRange.min) / projectionScale) + 1;
int projecction_yh = (int)((roi3D.yRange.max - roi3D.yRange.min) / projectionScale) + 1;
std::vector<std::vector<int>> projectionClusters;
projectionClusters.resize(projecction_xw);
for (int i = 0; i < projecction_yh; i++)
projectionClusters[i].resize(projecction_yh);
for (int i = 0; i < clusterNum; i++)
{
std::vector< SVzNL2DPoint>& a_cluster = clusters[i];
2026-03-10 16:57:56 +08:00
for (int j = 0; j < (int)a_cluster.size(); j++)
{
2026-03-10 16:57:56 +08:00
SVzNL2DPoint& a_pt = a_cluster[j];
SVzNL3DPosition& a_pt3d = scanLines[a_pt.x][a_pt.y];
int px = (int)((a_pt3d.pt3D.x - roi3D.xRange.min) / projectionScale);
int py = (int)((a_pt3d.pt3D.y - roi3D.yRange.min) / projectionScale);
2026-03-10 16:57:56 +08:00
if ((px < 0) || (px >= projecction_xw) || (py < 0) || (py >= projecction_yh))
int kkk = 1;
projectionClusters[px][py] = i + 1; //clusterID = index + 1
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>ݴ<EFBFBD>Сȷ<D0A1><C8B7>Բ<EFBFBD><D4B2>
std::vector<SVzNL3DPoint> clustersCenter;
clustersCenter.resize(clusters.size());
std::vector<int> validIndice;
double diameter_th = templateParam.holeDiameter * 0.1;
for (int i = 0; i < clusterNum; i++)
{
double xw = clustersRoi3D[i].xRange.max - clustersRoi3D[i].xRange.min;
double yh = clustersRoi3D[i].yRange.max - clustersRoi3D[i].yRange.min;
double xw_diff = abs(xw - templateParam.holeDiameter);
double yh_diff = abs(yh - templateParam.holeDiameter);
if ((xw_diff < diameter_th) && (yh_diff < diameter_th))
{
validIndice.push_back(i);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĵ<EFBFBD>
}
}
//Բ<><D4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ץȡ<D7A5><C8A1>
2026-03-10 16:57:56 +08:00
}
typedef struct
{
cv::RotatedRect rect;
cv::Point2f vertices[4];
}_RectParam;
//<2F><>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD><EFBFBD>߶Ȳ<DFB6><C8B2><EFBFBD>
void wd_computeSheetKeyHeigth(
std::vector< std::vector<SVzNL3DPosition>>& scanLines,
const SWD_sheetKeyParam sheetKeyParam,
const SSG_planeCalibPara groundCalibPara,
const SWD_sheetAlgoParam algoParam,
SWD_gripState* opState, //<2F><><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD><EFBFBD>ָʾ<D6B8><CABE>ǰ״̬
int* errCode,
std::vector<SWD_sheetGrasper>& resultObjPositions)
{
std::vector<std::vector< SVzNL2DPoint>> clusters;//ֻ<><D6BB>¼λ<C2BC><CEBB>
std::vector<SVzNL3DRangeD> clustersRoi3D;
//<2F><>ȡ<EFBFBD><C8A1>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ı<EFBFBD>Ե<EFBFBD><D4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
wd_computeClosedEdgeClusters(
scanLines,
groundCalibPara,
algoParam,
errCode,
clusters, //ֻ<><D6BB>¼λ<C2BC><CEBB>
clustersRoi3D);
int clusterNum = (int)clusters.size();
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//<2F><><EFBFBD>ݴ<EFBFBD>Сȷ<D0A1><C8B7><EFBFBD><EFBFBD>Ƭ
const double sameSizeTh_w = sheetKeyParam.sheetSize.width * 0.05;
const double sameSizeTh_h = sheetKeyParam.sheetSize.height * 0.05;
const double zAreaWin = 5;
std::vector<_RectParam> clustersRect;
clustersRect.resize(clusters.size());
#if 1
std::vector<int> validIndice;
for (int i = 0; i < clusterNum; i++)
{
std::vector< SVzNL2DPoint>& a_cluster = clusters[i];
if (a_cluster.size() < 4)
continue;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>Ӿ<EFBFBD>
std::vector<cv::Point2f> points;
SVzNLRect roi = { -1,-1,-1,-1 };
for (int j = 0; j < (int)a_cluster.size(); j++)
{
SVzNL2DPoint& a_pt = a_cluster[j];
SVzNL3DPosition& a_pt3d = scanLines[a_pt.x][a_pt.y];
//<2F><><EFBFBD><EFBFBD>ROI
if (roi.left < 0)
roi = { a_pt.x ,a_pt.x , a_pt.y, a_pt.y };
else
{
if (roi.left > a_pt.x)
roi.left = a_pt.x;
if (roi.right < a_pt.x)
roi.right = a_pt.x;
if (roi.top > a_pt.y)
roi.top = a_pt.y;
if (roi.bottom < a_pt.y)
roi.bottom = a_pt.y;
}
float x = (float)a_pt3d.pt3D.x;
float y = (float)a_pt3d.pt3D.y;
points.push_back(cv::Point2f(x, y));
}
if (points.size() == 0)
continue;
// <20><>С<EFBFBD><D0A1><EFBFBD>Ӿ<EFBFBD><D3BE><EFBFBD>
cv::RotatedRect rect = minAreaRect(points);
cv::Point2f vertices[4];
rect.points(vertices);
double width = rect.size.width; //ͶӰ<CDB6>Ŀ<EFBFBD><C4BF>͸ߣ<CDB8> <20><>Ӧ<EFBFBD><D3A6><EFBFBD>ӵij<D3B5><C4B3>Ϳ<EFBFBD>
double height = rect.size.height;
if (width < height)
{
double tmp = height;
height = width;
width = tmp;
}
int cx = (roi.left + roi.right) / 2;
int cy = (roi.top + roi.bottom) / 2;
//<2F>б<EFBFBD>
double w_diff = abs(width - sheetKeyParam.sheetSize.width);
double h_diff = abs(height - sheetKeyParam.sheetSize.height);
if ((w_diff < sameSizeTh_w) && (h_diff < sameSizeTh_h))
{
//Ѱ<>ҵ<EFBFBD>Ŀ<EFBFBD><C4BF>
//ȡ<><C8A1><EFBFBD>ĵ㣬<C4B5><E3A3AC><EFBFBD><EFBFBD><EFBFBD>ĵ㸽<C4B5><E3B8BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Z
int cx = (roi.left + roi.right) / 2;
int cy = (roi.top + roi.bottom) / 2;
SVzNLRect meanZRoi = { cx - zAreaWin , cx + zAreaWin , cy - zAreaWin , cy + zAreaWin };
double meanZ = computeROIMeanZ(scanLines, meanZRoi);
//<2F><><5A><D6B5>Ϊ<EFBFBD><CEAA><EFBFBD>޽<EFBFBD><DEBD><EFBFBD><EFBFBD>и<EFBFBD>
double cutZ = meanZ - sheetKeyParam.nominalKeyHeight * 0.75;
int labelID = i + 100; //ID<49><44>100<30><30>ʼ
computeROIZCutLabel(scanLines, roi, cutZ, labelID);
}
}
#endif
}