Commit deb5735c 张士柳

1 个父辈 04a46a32
......@@ -596,7 +596,7 @@ namespace eyemLib_Sharp
//eyemCountObjectIrregularParts(ucpImage, file.Replace(".png", ""), 0d, "IP_LONG_PARTS", 100, 5, ref pNumObj, out tpDstImg);
int ipNum; EyemBarCode* tpResults;
DataCodeHandle hObject;
int iRes = eyemDetectAndDecode(ucpImage, tpRoi, file.Replace(".png", ""), "QR_CODE|DATA_MATRIX|CODE_128|CODE_39", out hObject, out tpResults, out ipNum, false, 11, 5, 128, 215);
int iRes = eyemDetectAndDecode(ucpImage, tpRoi, file.Replace(".png", ""), "QR_CODE|DATA_MATRIX", out hObject, out tpResults, out ipNum, false, 11, 5, 128, 215, 1d);
for (int i = 0; i < ipNum; i++)
{
Console.WriteLine("类型:" + Marshal.PtrToStringAnsi(tpResults[i].hType) + ";坐标" + "[" + tpResults[i].iCenterX.ToString() + "," + tpResults[i].iCenterY.ToString() + "]" + ";角度:" + tpResults[i].dAngle.ToString("F4") + "," + ";内容:" + Marshal.PtrToStringAnsi(tpResults[i].hText) + "");
......
......@@ -346,33 +346,51 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
//优先当作DM来解码,因为它比较快
if (!waitAreas[i].oneD)
{
DmtxMessage *msg;
DmtxRegion *reg;
DmtxImage *img = dmtxImageCreate(waitAreas[i].waitArea.data, waitAreas[i].waitArea.cols, waitAreas[i].waitArea.rows, DmtxPack8bppK);
DmtxDecode *dec = dmtxDecodeCreate(img, 1);
//超时
DmtxTime beginTime = dmtxTimeNow();
DmtxTime timeout = dmtxTimeAdd(beginTime, 25);
reg = dmtxRegionFindNext(dec, &timeout);
if (NULL != reg)
cv::Mat binary;
//尝试多种参数解码
for (double d = waitAreas[i].C - (double)iRangeC; d <= waitAreas[i].C + (double)iRangeC; d += dMinorStep)
{
//解码
msg = dmtxDecodeMatrixRegion(dec, reg, DmtxUndefined);
if (NULL != msg)
cv::adaptiveThreshold(waitAreas[i].waitArea, binary, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, iBlockSize, d);
DmtxMessage *msg;
DmtxRegion *reg;
DmtxImage *img = NULL;
if (abs(d) == 0)
{
img = dmtxImageCreate(waitAreas[i].waitArea.data, waitAreas[i].waitArea.cols, waitAreas[i].waitArea.rows, DmtxPack8bppK);
}
else
{
bDecode = true;
ptResult = waitAreas[i].Pt;
strResultType = "DATA_MATRIX";
strResult = std::string(reinterpret_cast<const char *>(msg->output));
//销毁资源
dmtxMessageDestroy(&msg);
img = dmtxImageCreate(binary.data, waitAreas[i].waitArea.cols, waitAreas[i].waitArea.rows, DmtxPack8bppK);
}
//解码失败
dmtxRegionDestroy(&reg);
DmtxDecode *dec = dmtxDecodeCreate(img, 1);
//超时
DmtxTime beginTime = dmtxTimeNow();
DmtxTime timeout = dmtxTimeAdd(beginTime, 15);
reg = dmtxRegionFindNext(dec, &timeout);
if (NULL != reg)
{
//解码
msg = dmtxDecodeMatrixRegion(dec, reg, DmtxUndefined);
if (NULL != msg)
{
bDecode = true;
ptResult = waitAreas[i].Pt;
strResultType = "DATA_MATRIX";
strResult = std::string(reinterpret_cast<const char *>(msg->output));
//销毁资源
dmtxMessageDestroy(&msg);
}
//解码失败
dmtxRegionDestroy(&reg);
}
dmtxDecodeDestroy(&dec);
dmtxImageDestroy(&img);
//解码则结束循环
if (bDecode)
break;
}
dmtxDecodeDestroy(&dec);
dmtxImageDestroy(&img);
}
//如果未解码,判断可能是QR或者一维码或者DATA_MATRIX
if (!bDecode)
......@@ -389,7 +407,7 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
cv::pyrUp(src, src, cv::Size(src.cols * 2, src.rows * 2));
//判断解码结果
double threshVal = getThreshVal_Otsu_8u(src);
for (double c = threshVal - 4 * iRangeC; c < threshVal + 4 * iRangeC; c += dMinorStep)
for (double c = threshVal - 8 * iRangeC; c < threshVal + 8 * iRangeC; c += dMinorStep)
{
cv::Mat binary;
cv::threshold(src, binary, c, 255, cv::THRESH_BINARY);
......@@ -470,9 +488,9 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
if (std::find(hints.begin(), hints.end(), "QR_CODE") != hints.end()) {
readers_.push_back(Ref<Reader>(new zxing::qrcode::QRCodeReader));
}
if (std::find(hints.begin(), hints.end(), "DATA_MATRIX") != hints.end()) {
readers_.push_back(Ref<Reader>(new zxing::datamatrix::DataMatrixReader));
}
//if (std::find(hints.begin(), hints.end(), "DATA_MATRIX") != hints.end()) {
// readers_.push_back(Ref<Reader>(new zxing::datamatrix::DataMatrixReader));
//}
if (std::find(hints.begin(), hints.end(), "AZTEC") != hints.end()) {
readers_.push_back(Ref<Reader>(new zxing::aztec::AztecReader));
}
......@@ -519,9 +537,6 @@ static void decodeMul(std::vector<WaitArea> &waitAreas, std::vector<std::string>
}
}
}
//解码成功
breakLoop:
{
......@@ -612,16 +627,18 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
//检测热点图,s1用来检测一维码;s2用来检测二维码(条码来说会比背景值小,二维码来说会比背景值大)
cv::Mat s1(iY, iX, CV_8UC1, cv::Scalar(0)), s2(iY, iX, CV_8UC1, cv::Scalar(0));
//<//////////////////////通用预处理方式//////////////////////>//
cv::adaptiveThreshold(src, binary, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, iBlockSize, 2);
//突出条码部分
cv::morphologyEx(src, srcPrev, cv::MORPH_GRADIENT, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)));
//二值化
cv::Mat srcPrevBin;
cv::threshold(srcPrev, srcPrevBin, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
//略微膨胀覆盖条码
cv::morphologyEx(srcPrevBin, srcPrevBin, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(iBlockSize, iBlockSize)));
//尽量去掉无关区域
cv::bitwise_and(srcPrevBin, binary, binary);
cv::adaptiveThreshold(src, binary, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 83, 0);
////突出条码部分
//cv::morphologyEx(src, srcPrev, cv::MORPH_GRADIENT, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)));
////二值化
//cv::Mat srcPrevBin;
//cv::threshold(srcPrev, srcPrevBin, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
////略微膨胀覆盖条码
//cv::morphologyEx(srcPrevBin, srcPrevBin, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(iBlockSize, iBlockSize)));
////尽量去掉无关区域
//cv::bitwise_and(srcPrevBin, binary, binary);
//连通域分析
cv::Mat labels, stats, centroids;
int nccomps = cv::connectedComponentsWithStats(binary, labels, stats, centroids);
......@@ -629,8 +646,8 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
std::vector<uchar> colors(nccomps + 1, 0);
for (int i = 1; i < nccomps; i++) {
colors[i] = 255;
double maxSize = cv::max(stats.ptr<int>(i)[cv::CC_STAT_WIDTH], stats.ptr<int>(i)[cv::CC_STAT_HEIGHT]);
if ((stats.ptr<int>(i)[cv::CC_STAT_AREA] < 15) || (maxSize < ((double)iBlockSize)*(1. - dToleErr)) || (maxSize > 35 * iBlockSize))
double maxSize = cv::max(stats.ptr<int>(i)[cv::CC_STAT_WIDTH], stats.ptr<int>(i)[cv::CC_STAT_HEIGHT]); double minSize = cv::min(stats.ptr<int>(i)[cv::CC_STAT_WIDTH], stats.ptr<int>(i)[cv::CC_STAT_HEIGHT]);
if ((stats.ptr<int>(i)[cv::CC_STAT_AREA] < cvRound(10.0*dScaleUpAndDown)) || (minSize < (cvRound((double)iBlockSize*dScaleUpAndDown / 3.))) || (maxSize > 35 * iBlockSize))
{
colors[i] = 0;
}
......@@ -648,6 +665,28 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
}
}
});
//格式化文件名
const int bufSize = 32;
char file[bufSize * 4] = { 0 };
sprintf_s(file, "D:\\ResOut\\%s-Mark.png", ccFileName);
cv::imwrite(file, binary);
return FUNC_OK;
//膨胀区域
cv::Mat binaryEx;
cv::morphologyEx(binary, binaryEx, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(iBlockSize * 2, iBlockSize * 2)));
......@@ -707,14 +746,12 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
cv::morphologyEx(binary, mask, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(2 * iBlockSize + 1, 2 * iBlockSize + 1)));
//去掉干扰
cv::bitwise_and(s1, mask, s1);
///<进一步去除干扰
cv::morphologyEx(s1, s1, cv::MORPH_CLOSE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)));
//连通域分析
nccomps = cv::connectedComponentsWithStats(s1, labels, stats, centroids);
std::vector<uchar> colors2(nccomps + 1, 0);
for (int i = 1; i < nccomps; i++) {
colors2[i] = 255;
if ((stats.ptr<int>(i)[cv::CC_STAT_AREA] < std::pow(iBlockSize, 2)))
if ((stats.ptr<int>(i)[cv::CC_STAT_AREA] < std::pow(iRealBlockSize, 2)))
{
colors2[i] = 0;
}
......@@ -733,6 +770,161 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
}
});
//后续识别
//用于轮廓检测
std::vector<std::vector<cv::Point>> contourAll, contourFilter;
findContours(s1, contourAll, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
//初步过滤
for (int i = 0; i < int(contourAll.size()); i++)
{
cv::RotatedRect rect = cv::minAreaRect(contourAll[i]);
double dRate = (double)cv::max(rect.size.height, rect.size.width) / (double)cv::min(rect.size.height, rect.size.width), rgt = cv::contourArea(contourAll[i]) / rect.size.area();
if ((cv::min(rect.size.height, rect.size.width) > iBlockSize * 2) && (cv::contourArea(contourAll[i]) / rect.size.area()) > 0.35)
{
contourFilter.push_back(contourAll[i]);
}
else
cv::drawContours(s1, contourAll, i, cv::Scalar(0), -1);
}
//按照条形码特征过滤
for (int i = 0; i < static_cast<int>(contourFilter.size()); i++)
{
cv::RotatedRect rect = cv::minAreaRect(contourFilter[i]);
//最大宽度限制
double minLen = cv::min(rect.size.height, rect.size.width);
if (minLen < 8.*iBlockSize*(1. + dToleErr))
{
//增加比例过滤条件
cv::Point2f pts[4];
rect.points(pts);
//起点、终点、中点
cv::Point ptStart, ptEnd, ptMid;
if (cv::norm(pts[0] - pts[1]) > cv::norm(pts[1] - pts[2]))
{
ptStart = cv::Point((pts[0] + pts[3]) / 2.); ptEnd = cv::Point((pts[1] + pts[2]) / 2.);
}
else
{
ptStart = cv::Point((pts[0] + pts[1]) / 2.); ptEnd = cv::Point((pts[2] + pts[3]) / 2.);
}
ptMid = (ptStart + ptEnd) / 2;
cv::LineIterator it(binary, (ptMid + ptEnd) / 2, (ptMid + ptStart) / 2, 4);
double dis = cv::norm((ptMid + ptEnd) / 2 - (ptMid + ptStart) / 2);
uint8_t future_pixel = 255;
//扫描像素密度,比例接近1:1记录下来,并且黑白间隔数目小大于长度的一半
int flag = 0;
double test_line[2]{ 0 };
for (int n = 0; n < it.count; n++, ++it)
{
if (s1.ptr<uint8_t>(cvRound(it.pos().y))[cvRound(it.pos().x)] == 0) continue;
//统计均匀性
uint8_t next_pixel = binary.ptr<uint8_t>(it.pos().y)[it.pos().x];
test_line[next_pixel % 254]++;
if (next_pixel != future_pixel)
{
flag++;
future_pixel = 255 - future_pixel;
}
showMat.at<cv::Vec3b>(it.pos()) = cv::Vec3b(0, 255, 0);
}
//满足比例
double dRate = cv::min(test_line[0], test_line[1]) / cv::max(test_line[0], test_line[1]);
if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr) && flag > cvRound((dis / 4.)*(1. - dToleErr)))
{
cv::Point2f pt[4];
cv::Size size(cvRound(cv::max(rect.size.height, rect.size.width) + 4 * iBlockSize / 2.), cvRound(cv::min(rect.size.height, rect.size.width)));
//获取roi位置
double _angle = std::atan2((ptEnd.y - ptStart.y), (ptEnd.x - ptStart.x));
float b = (float)cos(_angle)*0.5f;
float a = (float)sin(_angle)*0.5f;
pt[0].x = rect.center.x - a*size.height - b*size.width;
pt[0].y = rect.center.y + b*size.height - a*size.width;
pt[1].x = rect.center.x + a*size.height - b*size.width;
pt[1].y = rect.center.y - b*size.height - a*size.width;
pt[2].x = 2 * rect.center.x - pt[0].x;
pt[2].y = 2 * rect.center.y - pt[0].y;
pt[3].x = 2 * rect.center.x - pt[1].x;
pt[3].y = 2 * rect.center.y - pt[1].y;
//防止越界
for (int n = 0; n < 4; n++)
{
if (pt[n].x < 0) pt[n].x = 0.f; if (pt[n].x >= iX - 1) pt[n].x = float(iX - 1); if (pt[n].y < 0) pt[n].y = 0.f; if (pt[n].y >= iY - 1) pt[n].y = float(iY - 1);
}
//用采样的方式提取待解码区域
cv::LineIterator itStHeight(realSrc, pt[0], pt[1], 4);
cv::LineIterator itEdHeight(realSrc, pt[3], pt[2], 4);
cv::LineIterator itStWidth(realSrc, pt[0], pt[3], 4);
cv::LineIterator itEdWidth(realSrc, pt[1], pt[2], 4);
struct Track
{
cv::Point PosS;
cv::Point PosE;
Track() {};
Track(cv::Point PosS, cv::Point PosE) :PosS(PosS), PosE(PosE) {};
};
std::vector<Track> pairStEd(cv::min(itStHeight.count, itEdHeight.count));
for (int n = 0; n < pairStEd.size(); n++, ++itStHeight, ++itEdHeight)
{
pairStEd[n] = Track(itStHeight.pos(), itEdHeight.pos());
}
int iSamplingStep = int(pairStEd.size()) / 4;
//线采样
cv::Mat srcSampling(cv::Size(cv::max(itStWidth.count, itEdWidth.count), 1), CV_8UC1, cv::Scalar(255));
//
std::vector<cv::Mat> oneDMats;
//行
for (int n = 0; n < (int)pairStEd.size(); n += iSamplingStep)
{
cv::LineIterator it(realSrc, pairStEd[n].PosS, pairStEd[n].PosE, 4);
for (int nn = 0; nn < it.count; nn++, ++it)//列
{
//showMat.at<cv::Vec3b>(it.pos()) = cv::Vec3b(0, 255, 0);
srcSampling.ptr<uint8_t>(0)[nn] = realSrc.ptr<uint8_t>(it.pos().y)[it.pos().x];
}
//判断是否为二维码
cv::Mat testMat;
cv::threshold(srcSampling, testMat, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
//
cv::Mat testLabels;
if (cv::connectedComponents(testMat, testLabels) < 6)
{
//判断非二维码
break;
}
//扩展
cv::Mat waitArea;
cv::copyMakeBorder(srcSampling, waitArea, 0, 1, 60, 60, cv::BORDER_REPLICATE);
oneDMats.push_back(waitArea);
}
//存储一维码待解码区域
if ((int)oneDMats.size() > 0)
{
//画图
for (int j = 0; j < 4; j++)
{
cv::line(showMat, pt[j], pt[(j + 1) % 4], cv::Scalar(0, 255, 255), 1);
}
//cv::circle(showMat, pt[0], 2, cv::Scalar(255, 0, 0), -1);
//cv::circle(showMat, pt[1], 2, cv::Scalar(0, 255, 0), -1);
//cv::circle(showMat, pt[2], 2, cv::Scalar(0, 0, 255), -1);
waitAreas.push_back(WaitArea(cv::Mat(), ptMid, getThreshVal_Otsu_8u(oneDMats[0]), _angle*180. / PI, true, oneDMats));
}
}
}
}
}
//添加二维码识别
if (addTwoDReader)
......@@ -779,84 +971,86 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
//用于轮廓检测
std::vector<std::vector<cv::Point>> contourAll, contourFilter;
findContours(s2, contourAll, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
for (int i = 0; i < static_cast<int>(contourAll.size()); i++)
{
cv::RotatedRect rec = cv::minAreaRect(contourAll[i]);
//偏移量
cv::Point2f pts[4];
rec.points(pts);
//满足矩形条件与面积条件
double dRate = cv::min(rec.size.width, rec.size.height) / cv::max(rec.size.height, rec.size.width);
if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr) && cv::min(rec.size.width, rec.size.height) > 20)
{
int dynSize = cvRound(cv::max((double)rec.boundingRect().size().height / dScaleUpAndDown, (double)rec.boundingRect().size().width / dScaleUpAndDown));
//用原图来进行过滤最好
cv::Mat waitArea = realSrc(cv::Range(cv::max(0, cvRound(rec.center.y / dScaleUpAndDown) - (2 * iBlockSize + dynSize / 2)), cv::min(iRealY - 1, cvRound(rec.center.y / dScaleUpAndDown) + (2 * iBlockSize + dynSize / 2))), cv::Range(cv::max(0, cvRound(rec.center.x / dScaleUpAndDown) - (2 * iBlockSize + dynSize / 2)), cv::min(iRealX - 1, cvRound(rec.center.x / dScaleUpAndDown) + (2 * iBlockSize + dynSize / 2))));
//计算响应图
cv::Mat harMap;
cv::cornerHarris(waitArea, harMap, iRealBlockSize, 3, 0.04);
// 归一化与转换
cv::normalize(harMap, harMap, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
cv::convertScaleAbs(harMap, harMap);
//进一步判断
cv::Mat m2 /*= harMap > calcHist(harMap)*/;
cv::threshold(harMap, m2, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
//
cv::morphologyEx(m2, m2, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(cvRound((double)iRealBlockSize / 3.), cvRound((double)iRealBlockSize / 3.))));
//用于轮廓检测
std::vector<std::vector<cv::Point>> contours;
findContours(m2, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
//最大轮廓
std::vector<cv::Point> contourMax = contours[0];
for (int cc = 0; cc < contours.size(); cc++)
{
if (cv::contourArea(contours[cc]) > cv::contourArea(contourMax))
{
contourMax = contours[cc];
}
}
//未过滤前
cv::rectangle(showMat, cv::minAreaRect(contourAll[i]).boundingRect(), cv::Scalar(0, 0, 255), 1);
////扫描线
//cv::Point ptStart, ptEnd;
//ptStart = cv::Point(pts[0]); ptEnd = cv::Point(pts[2]);
rec = cv::minAreaRect(contourMax);
dRate = cv::min(rec.size.width, rec.size.height) / cv::max(rec.size.height, rec.size.width);
//判断比例
if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr) && cv::min(rec.size.width, rec.size.height) > 20)
{
double dRateA = std::pow(cv::min(rec.size.height, rec.size.width), 2) / std::pow(dynSize, 2);
if (dRateA >= 0.5*(1. - dToleErr))
{
////按照比例过滤
//int flags = 0;
//double test_line[2]{ 0 };
//cv::LineIterator it(binary, ptStart, ptEnd, 4);
//uint8_t future_pixel = 0;
//for (int n = 0; n < it.count; n++, ++it)
//{
// //统计均匀性
// uint8_t next_pixel = binary.ptr<uint8_t>(it.pos().y)[it.pos().x];
// test_line[next_pixel % 254]++;
// if (next_pixel != future_pixel)
// {
// flags++;
// future_pixel = 255 - future_pixel;
// }
//}
////判断是否满足比例
//double dRate = cv::min(test_line[0], test_line[1]) / cv::max(test_line[0], test_line[1]);
//if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr))
//{
cv::rectangle(showMat, cv::minAreaRect(contourAll[i]).boundingRect(), cv::Scalar(0, 255, 0), 1);
//}
}
}
}
}
//for (int i = 0; i < static_cast<int>(contourAll.size()); i++)
//{
// cv::RotatedRect rec = cv::minAreaRect(contourAll[i]);
// //偏移量
// cv::Point2f pts[4];
// rec.points(pts);
// //满足矩形条件与面积条件
// double dRate = cv::min(rec.size.width, rec.size.height) / cv::max(rec.size.height, rec.size.width);
// if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr) && cv::min(rec.size.width, rec.size.height) > 20)
// {
// int dynSize = cvRound(cv::max((double)rec.boundingRect().size().height / dScaleUpAndDown, (double)rec.boundingRect().size().width / dScaleUpAndDown));
// //用原图来进行过滤最好
// cv::Mat waitArea = realSrc(cv::Range(cv::max(0, cvRound(rec.center.y / dScaleUpAndDown) - (2 * iBlockSize + dynSize / 2)), cv::min(iRealY - 1, cvRound(rec.center.y / dScaleUpAndDown) + (2 * iBlockSize + dynSize / 2))), cv::Range(cv::max(0, cvRound(rec.center.x / dScaleUpAndDown) - (2 * iBlockSize + dynSize / 2)), cv::min(iRealX - 1, cvRound(rec.center.x / dScaleUpAndDown) + (2 * iBlockSize + dynSize / 2))));
// //计算响应图
// cv::Mat harMap;
// cv::cornerHarris(waitArea, harMap, iRealBlockSize, 3, 0.04);
// // 归一化与转换
// cv::normalize(harMap, harMap, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
// cv::convertScaleAbs(harMap, harMap);
// //进一步判断
// cv::Mat m2;
// cv::threshold(harMap, m2, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
// ////测试用
// //cv::Mat locBinary;
// //cv::threshold(waitArea, locBinary, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
// //连接断裂处
// cv::morphologyEx(m2, m2, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(cvRound((double)iRealBlockSize / 3.), cvRound((double)iRealBlockSize / 3.))));
// //用于轮廓检测
// std::vector<std::vector<cv::Point>> contours;
// findContours(m2, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
// //最大轮廓
// std::vector<cv::Point> contourMax = contours[0];
// for (int cc = 0; cc < contours.size(); cc++)
// {
// if (cv::contourArea(contours[cc]) > cv::contourArea(contourMax))
// {
// contourMax = contours[cc];
// }
// }
// ////扫描线
// //cv::Point ptStart, ptEnd;
// //ptStart = cv::Point(pts[0]); ptEnd = cv::Point(pts[2]);
// rec = cv::minAreaRect(contourMax);
// dRate = cv::min(rec.size.width, rec.size.height) / cv::max(rec.size.height, rec.size.width);
// //判断比例
// if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr) && cv::min(rec.size.width, rec.size.height) > 20)
// {
// double dRateA = std::pow(cv::min(rec.size.height, rec.size.width), 2) / std::pow(dynSize, 2);
// if (dRateA >= 0.5*(1. - dToleErr))
// {
// ////按照比例过滤
// //int flags = 0;
// //double test_line[2]{ 0 };
// //cv::LineIterator it(binary, ptStart, ptEnd, 4);
// //uint8_t future_pixel = 0;
// //for (int n = 0; n < it.count; n++, ++it)
// //{
// // //统计均匀性
// // uint8_t next_pixel = binary.ptr<uint8_t>(it.pos().y)[it.pos().x];
// // test_line[next_pixel % 254]++;
// // if (next_pixel != future_pixel)
// // {
// // flags++;
// // future_pixel = 255 - future_pixel;
// // }
// //}
// ////判断是否满足比例
// //double dRate = cv::min(test_line[0], test_line[1]) / cv::max(test_line[0], test_line[1]);
// //if (dRate >= (1. - dToleErr) && dRate <= (1. + dToleErr))
// //{
// //cv::rectangle(showMat, cv::minAreaRect(contourAll[i]).boundingRect(), cv::Scalar(0, 255, 0), 1);
// contourFilter.push_back(contourAll[i]);
// //}
// }
// }
// }
//}
//for (int i = 0; i < contourFilter.size(); i++)
//{
// cv::Rect rect = cv::minAreaRect(contourFilter[i]).boundingRect();
......@@ -869,23 +1063,62 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
// waitAreas.push_back(WaitArea(waitArea, cv::Point(cvRound(rRect.center.x / dScaleUpAndDown), cvRound(rRect.center.y / dScaleUpAndDown)), 0, 0, false, std::vector<cv::Mat>()));
// //画图
// cv::rectangle(showMat, rect, cv::Scalar(0, 255, 0), 1);
// //cv::Point2f points[4];
// //rec.points(points);
// //for (int j = 0; j < 4; j++)
// //{
// // cv::line(showMat, points[j], points[(j + 1) % 4], cv::Scalar(0, 165, 255, 255), 1);
// //}
//}
}
//最后解码用原图来解码
//格式化文件名
const int bufSize = 32;
char file[bufSize * 4] = { 0 };
sprintf_s(file, "D:\\ResOut\\%s-Mark.png", ccFileName);
cv::imwrite(file, showMat);
////解码
//decodeMul(waitAreas, hints_, showMat, decodeResults, iBlockSize, iRangeC, dMinorStep);
////输出结果
//for (int i = 0; i < decodeResults.size(); i++)
//{
// EyemBarCode tpResult;
// tpResult.iCenterX = decodeResults[i].ptResult.x;
// tpResult.iCenterY = decodeResults[i].ptResult.y;
// tpResult.dAngle = decodeResults[i].dAngle;
// //分配内容所需内存
// tpResult.lpszText = (char *)CoTaskMemAlloc(512);
// if (NULL != tpResult.lpszText)
// {
// char file[512] = { 0 };
// sprintf_s(file, "%s", decodeResults[i].strResultText.c_str());
// strcpy(tpResult.lpszText, file);
// }
// else return FUNC_NOT_ENOUGH_MEM;
// //分配码型所需内存
// tpResult.lpszType = (char *)CoTaskMemAlloc(512);
// if (NULL != tpResult.lpszType)
// {
// char file[512] = { 0 };
// sprintf_s(file, "%s", decodeResults[i].strResultType.c_str());
// strcpy(tpResult.lpszType, file);
// }
// else return FUNC_NOT_ENOUGH_MEM;
// //添加结果
// tpResults->push_back(tpResult);
//}
//*hResults = tpResults->data();
//*ipNum = static_cast<int>(tpResults->size());
//*hObject = reinterpret_cast<IntPtr>(tpResults);
return FUNC_OK;
//计算导数
cv::Mat dx, dy, mag;
cv::Sobel(srcPrev, dx, CV_32F, 1, 0);
......@@ -1275,39 +1508,7 @@ int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileNam
cv::rectangle(showMat, rect, cv::Scalar(0, 255, 0), 1);
}
}
//解码
decodeMul(waitAreas, hints_, showMat, decodeResults, iBlockSize, iRangeC, dMinorStep);
//输出结果
for (int i = 0; i < decodeResults.size(); i++)
{
EyemBarCode tpResult;
tpResult.iCenterX = decodeResults[i].ptResult.x;
tpResult.iCenterY = decodeResults[i].ptResult.y;
tpResult.dAngle = decodeResults[i].dAngle;
//分配内容所需内存
tpResult.lpszText = (char *)CoTaskMemAlloc(512);
if (NULL != tpResult.lpszText)
{
char file[512] = { 0 };
sprintf_s(file, "%s", decodeResults[i].strResultText.c_str());
strcpy(tpResult.lpszText, file);
}
else return FUNC_NOT_ENOUGH_MEM;
//分配码型所需内存
tpResult.lpszType = (char *)CoTaskMemAlloc(512);
if (NULL != tpResult.lpszType)
{
char file[512] = { 0 };
sprintf_s(file, "%s", decodeResults[i].strResultType.c_str());
strcpy(tpResult.lpszType, file);
}
else return FUNC_NOT_ENOUGH_MEM;
//添加结果
tpResults->push_back(tpResult);
}
*hResults = tpResults->data();
*ipNum = static_cast<int>(tpResults->size());
*hObject = reinterpret_cast<IntPtr>(tpResults);
return FUNC_OK;
}
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!