Commit 900f2b4e 张士柳

1 个父辈 9b87c7a1
......@@ -776,6 +776,9 @@ namespace eyemLib_Sharp
//基于深度学习读码程序(仅支持QR、DataMatrix)
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, out DataCodeHandle hObject, out EyemBarCode* tpResults, out int ipNum, out EyemImage tpDstImg);
//基于深度学习一维码读码程序()
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, out DataCodeHandle hObject, out EyemBarCode* tpResults, out int ipNum, out EyemImage tpDstImg);
//加载模型配置文件
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemInitNNDataCodeModel(string detectorConfigPath, string detectorModelPath, string superResolutionConfigPath, string superResolutionModelPath);
......@@ -788,6 +791,9 @@ namespace eyemLib_Sharp
//跳过程序执行
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int setSkipProcessID(int pid);
//圆形mark点定位
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemMarkerTracing(EyemImage tpImage, double dThreshold, ref EyemOcsFXYR tpCircle, bool bHighAccuracy = false);
#endregion
#region 测试接口
......@@ -819,7 +825,7 @@ namespace eyemLib_Sharp
OnNewLogCallback += new TCallBack(EyemLib_OnNewLogCallback);
eyemInitNNDataCodeModel(".\\darknet\\detect-tiny.cfg", ".\\darknet\\detect-tiny.weights", "", "");
eyemInitNNDataCodeModel(".\\darknet\\detect-tiny.cfg", ".\\darknet\\detect-tiny.weights", ".\\darknet\\sr.prototxt", ".\\darknet\\sr.caffemodel");
}
public static void Free()
......@@ -853,6 +859,8 @@ namespace eyemLib_Sharp
Console.WriteLine("读图失败!");
return;
}
Stopwatch sw = new Stopwatch();
sw.Restart();
//flag = eyemImageMalloc(image.iWidth, image.iHeight, 1, "uint16_t", out image1);
//flag = eyemImageMalloc(image.iWidth, image.iHeight, 1, "int8_t", out image2);
......@@ -869,7 +877,8 @@ namespace eyemLib_Sharp
//flag = eyemLibImpl(image, out tpDstImg);
//EyemOcsFXYR tpCircle = new EyemOcsFXYR();
//flag = eyemMarkerTracing(image, 130, ref tpCircle);
#region Test Blob
......@@ -1094,8 +1103,7 @@ namespace eyemLib_Sharp
//{
// bitmap.Save("D:\\ResOut\\" + file);
//}
Stopwatch sw = new Stopwatch();
sw.Restart();
//< 解码测试
int ipNum; EyemBarCode* tpResults;
DataCodeHandle hObject;
......@@ -1107,17 +1115,18 @@ namespace eyemLib_Sharp
//}
//hObject.Dispose();
flag = eyemDetectAndDecodeUseNN(image, tpRoi, out hObject, out tpResults, out ipNum, out tpDstImg);
//flag = eyemDetectAndDecodeUseNN(image, tpRoi, out hObject, out tpResults, out ipNum, out tpDstImg);
flag = eyemDetectAndDecodeBarcodeUseNN(image, tpRoi, out hObject, out tpResults, out ipNum, out tpDstImg);
sw.Stop();
Console.WriteLine(file + "--->" + "耗时:" + sw.ElapsedMilliseconds.ToString() + ",结果:" + pNumObj);
//Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
Bitmap bitmap = eyemCvtToBitmap(tpDstImg);
//if (bitmap != null)
//{
// bitmap.Save("D:\\ResOut\\" + file);
//}
if (bitmap != null)
{
bitmap.Save("D:\\ResOut\\" + file);
}
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) + "");
......
......@@ -388,6 +388,20 @@ bool BarcodeDetector::computeTransformationPoints() {
return !transformation_points.empty();
}
static int calcHist(cv::Mat src)
{
const int histSize = 256;
float range[] = { 0,255 };
const float* histRange = { range };
//calculate the histogram
cv::Mat hist;
cv::calcHist(&src, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange);
//calculate the background pixels
int maxIdx[2] = { 255,255 };
cv::minMaxIdx(hist, NULL, NULL, NULL, maxIdx);
return maxIdx[0];
}
bool BarcodeDetector::detect(cv::Mat img, std::vector<cv::Point>& points)
{
......@@ -395,6 +409,22 @@ bool BarcodeDetector::detect(cv::Mat img, std::vector<cv::Point>& points)
if (!checkBarInputImage(img, inarr)) {
return false;
}
//
//static constexpr float SCALE_LIST[] = { 0.005, 0.01f, 0.03f, 0.06f, 0.08f };
//const auto min_side = static_cast<float>(std::min(inarr.cols, inarr.rows));
//int window_size;
//for (const float scale : SCALE_LIST)
//{
// window_size = cvRound(min_side * scale);
// cv::Mat harMap;
// cv::cornerHarris(inarr, harMap, window_size, 3, 0.04);
// // һת
// cv::normalize(harMap, harMap, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat());
// cv::convertScaleAbs(harMap, harMap);
// cv::Mat sr = harMap < calcHist(harMap);
//}
//return true;
init(inarr);
localization();
if (!computeTransformationPoints()) {
......
#include "eyemBarCode.h"
#include "eyemDataCode.h"
#pragma region 内部使用函数
......@@ -909,50 +909,53 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject,
std::vector<cv::Rect> points; std::vector<cv::Rect> __points;
auto results = detector->detectAndDecode(image, points, __points);
//std::string str(enumtoCharArr(EYEM_DIST_HUBER));
#pragma region discard
//if (image.channels() == 1) {
// cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
//}
//else if (image.channels() == 4) {
// cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
//}
//cv::Mat showMat = image.clone();
//for (auto&point : points) {
// cv::rectangle(showMat, point, cv::Scalar(0, 255, 0), 2);
//}
//for (auto&point : __points) {
// cv::rectangle(showMat, point, cv::Scalar(0, 0, 255), 2);
//}
//for (int c = 0; c < results.size(); c++) {
// int baseLine;
// std::string label = results[c];
// cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
// cv::Scalar pal(0, 255, 0);
// cv::rectangle(showMat, cv::Point(points[c].tl().x, points[c].tl().y - labelSize.height - baseLine), cv::Point(points[c].tl().x + labelSize.width, points[c].tl().y), pal, cv::FILLED);
// cv::putText(showMat, label, cv::Point(points[c].tl().x, points[c].tl().y - baseLine), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1);
//}
/////<输出结果图像
//{
// tpDstImg->iWidth = showMat.cols; tpDstImg->iHeight = showMat.rows; tpDstImg->iDepth = showMat.depth(); tpDstImg->iChannels = showMat.channels();
// //内存尺寸
// int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t);
// //分配初始化内存
// tpDstImg->vpImage = (uint8_t *)malloc(_Size);
// if (NULL == tpDstImg->vpImage)
// return FUNC_NOT_ENOUGH_MEM;
// memset(tpDstImg->vpImage, 0, _Size);
// //拷贝数据
// memcpy(tpDstImg->vpImage, showMat.data, _Size);
//}
if (image.channels() == 1) {
cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
}
else if (image.channels() == 4) {
cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
}
cv::Mat showMat = image.clone();
for (auto&point : __points) {
cv::rectangle(showMat, point, cv::Scalar(0, 0, 255), 2);
}
for (auto&point : points) {
cv::rectangle(showMat, point, cv::Scalar(0, 255, 0), 2);
}
for (int c = 0; c < results.size(); c++) {
int baseLine;
std::string label = results[c];
cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
cv::Scalar pal(0, 255, 0);
cv::rectangle(showMat, cv::Point(points[c].tl().x, points[c].tl().y - labelSize.height - baseLine), cv::Point(points[c].tl().x + labelSize.width, points[c].tl().y), pal, cv::FILLED);
cv::putText(showMat, label, cv::Point(points[c].tl().x, points[c].tl().y - baseLine), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1);
}
///<输出结果图像
{
tpDstImg->iWidth = showMat.cols; tpDstImg->iHeight = showMat.rows; tpDstImg->iDepth = showMat.depth(); tpDstImg->iChannels = showMat.channels();
//内存尺寸
int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t);
//分配初始化内存
tpDstImg->vpImage = (uint8_t *)malloc(_Size);
if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据
memcpy(tpDstImg->vpImage, showMat.data, _Size);
}
#pragma endregion
//解码结果
......@@ -990,6 +993,91 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject,
return FUNC_OK;
}
int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject, EyemBarCode **hResults, int *ipNum, EyemImage *tpDstImg)
{
cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
if (image.empty()) {
return FUNC_IMAGE_NOT_EXIST;
}
if (image.channels() == 1) {
cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
}
else if (image.channels() == 4) {
cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
}
cv::Mat showMat = image.clone();
//识别并解码
std::vector<cv::Point> points;
auto results = detector->detectAndDecodeBarcode(image, showMat, points);
#pragma region discard
for (int c = 0; c < results.size(); c++) {
int baseLine;
std::string label = results[c];
cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
cv::Scalar pal(0, 255, 255);
cv::rectangle(showMat, cv::Point(points[c].x, points[c].y - labelSize.height - baseLine), cv::Point(points[c].x + labelSize.width, points[c].y), pal, cv::FILLED);
cv::putText(showMat, label, cv::Point(points[c].x, points[c].y - baseLine), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1);
}
///<输出结果图像
{
tpDstImg->iWidth = showMat.cols; tpDstImg->iHeight = showMat.rows; tpDstImg->iDepth = showMat.depth(); tpDstImg->iChannels = showMat.channels();
//内存尺寸
int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t);
//分配初始化内存
tpDstImg->vpImage = (uint8_t *)malloc(_Size);
if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据
memcpy(tpDstImg->vpImage, showMat.data, _Size);
}
#pragma endregion
//解码结果
std::vector<EyemBarCode> *tpResults = new std::vector<EyemBarCode>();
for (int n = 0; n < results.size(); n++) {
EyemBarCode tpResult;
tpResult.iCenterX = points[n].x;
tpResult.iCenterY = points[n].y;
tpResult.dAngle = 0;
//分配内容所需内存
tpResult.lpszText = (char *)CoTaskMemAlloc(256);
if (NULL != tpResult.lpszText)
{
char file[512] = { 0 };
sprintf_s(file, "%s", results[n].c_str());
strcpy(tpResult.lpszText, file);
}
else return FUNC_NOT_ENOUGH_MEM;
//分配码型所需内存
tpResult.lpszType = (char *)CoTaskMemAlloc(256);
if (NULL != tpResult.lpszType)
{
char file[512] = { 0 };
sprintf_s(file, "%s", "BARCODE");
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;
}
int eyemInitNNDataCodeModel(const char *detectorConfigPath, const char *detectorModelPath, const char *superResolutionConfigPath, const char *superResolutionModelPath)
{
try
......
......@@ -2,11 +2,11 @@
//
// eyemBarCode·标头
//
#ifndef __EYEM_BARCODE_H
#define __EYEM_BARCODE_H
#ifndef __EYEM_DATACODE_H
#define __EYEM_DATACODE_H
#include "eyemLib.h"
#include "nndetector.h"
#include "nnDetector.h"
std::mutex mtx;
......@@ -57,4 +57,4 @@ struct DecodeResult
};
#endif/* __EYEM_BARCODE_H */
\ No newline at end of file
#endif/* __EYEM_DATACODE_H */
\ No newline at end of file
......@@ -308,48 +308,6 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d
return FUNC_OK;
}
int fitCircle2D(int iPtnNum, EyemOcsDXY2D *taPoint, int iCalcMode, EyemOcsDXYR &tpCircle) {
if (iPtnNum <= 0) {
return 0;
}
std::vector<cv::Point2d> points;
for (int i = 0; i < iPtnNum; i++)
{
if (taPoint[i].bValid)
{
points.push_back(cv::Point2d(taPoint[i].dX, taPoint[i].dY));
}
}
//计算系数
double sa[9], sb[3], sx[3];
cv::Mat a = cv::Mat(3, 3, CV_64F, sa), b = cv::Mat(3, 1, CV_64F, sb);
//系数矩阵A*X=B;
cv::Mat x = cv::Mat(3, 1, CV_64F, sx);
std::memset(sa, 0, sizeof(sa));
std::memset(sb, 0, sizeof(sb));
for (int i = 0; i < iPtnNum; i++)
{
sa[0] += (double)points[i].x;
sa[1] += (double)points[i].y;
sa[2] += 1.0;
sa[3] += (double)points[i].x*(double)points[i].x;
sa[4] += (double)points[i].x*(double)points[i].y;
sa[7] += (double)points[i].y*(double)points[i].y;
sb[1] += (double)points[i].x*(-(double)points[i].x*(double)points[i].x - (double)points[i].y*(double)points[i].y);
sb[2] += (double)points[i].y*(-(double)points[i].x*(double)points[i].x - (double)points[i].y*(double)points[i].y);
}
sa[5] = sa[0];
sa[6] = sa[4];
sa[8] = sa[1];
sb[0] = -(sa[3] + sa[7]);
cv::solve(a, b, x, cv::DECOMP_SVD);
tpCircle.dX = -(*x.ptr<double>(0)) / 2.0;
tpCircle.dY = -(*x.ptr<double>(1)) / 2.0;
tpCircle.dR = sqrt(pow((*x.ptr<double>(0)), 2) + pow((*x.ptr<double>(1)), 2) - (*x.ptr<double>(2)));
return 1;
}
int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgnore, EyemOcsDABC &tpLine)
{
//int maxiter = 50;
......@@ -411,15 +369,55 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgnore
return FUNC_OK;
}
int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgnore, EyemOcsDXYR &tpCircle)
{
int maxiter = 50;
double min_err = DBL_MAX, err = 0;
int fitCircle2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsDXYR &tpCircle) {
if (iPtnNum <= 0) {
return 0;
}
std::vector<cv::Point2d> points;
for (int i = 0; i < iPtnNum; i++)
{
if (taPoints[i].bValid)
{
points.push_back(cv::Point2d(taPoints[i].dX, taPoints[i].dY));
}
}
//计算系数
double sa[9], sb[3];
cv::Mat a = cv::Mat(3, 3, CV_64F, sa), b = cv::Mat(3, 1, CV_64F, sb);
//系数矩阵A*X=B;
cv::Mat x = cv::Mat(3, 1, CV_64F);
memset(sa, 0, sizeof(sa));
memset(sb, 0, sizeof(sb));
for (size_t i = 0; i < points.size(); i++)
{
sa[0] += (double)points[i].x;
sa[1] += (double)points[i].y;
sa[2] += 1.0;
sa[3] += (double)points[i].x*(double)points[i].x;
sa[4] += (double)points[i].x*(double)points[i].y;
sa[7] += (double)points[i].y*(double)points[i].y;
sb[1] += (double)points[i].x*(-(double)points[i].x*(double)points[i].x - (double)points[i].y*(double)points[i].y);
sb[2] += (double)points[i].y*(-(double)points[i].x*(double)points[i].x - (double)points[i].y*(double)points[i].y);
}
sa[5] = sa[0];
sa[6] = sa[4];
sa[8] = sa[1];
sb[0] = -(sa[3] + sa[7]);
cv::solve(a, b, x, cv::DECOMP_SVD);
tpCircle.dX = -x.ptr<double_t>(0)[0] / 2.0;
tpCircle.dY = -x.ptr<double_t>(1)[0] / 2.0;
tpCircle.dR = sqrt(pow(x.ptr<double_t>(0)[0], 2) + pow(x.ptr<double_t>(1)[0], 2) - 4.0*(x.ptr<double_t>(2)[0])) / 2.0;
return 1;
}
int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgnore, double &RMS, EyemOcsDXYR &tpCircle)
{
//初始化参数,或许可用RANSAC算法进一步提高鲁棒性,不过没必要
if (numToIgnore > iPtnNum - 3 || iPtnNum < 3) {
return FUNC_CANNOT_CALC;
}
EyemOcsDXY2D *taPoints = new EyemOcsDXY2D[iPtnNum];
std::vector<EyemOcsDXY2D> taPoints(iPtnNum);
for (int i = 0; i < iPtnNum; i++)
{
taPoints[i].bValid = true;
......@@ -427,11 +425,10 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgno
taPoints[i].dY = taPoint[i].dY;
taPoints[i].dE = EPS;
}
//初始化参数,或许可用RANSAC算法进一步提高鲁棒性,不过没必要
fitCircle2D(iPtnNum, taPoints, iCalcMode, tpCircle);
double rms = .0;
fitCircle2D_wods(iPtnNum, &taPoints[0], tpCircle);
//迭代计算
for (int it = 0; it < maxiter; it++)
for (int it = 0; it < 50; it++)
{
double sr = 0.0, r = 0.0;
for (int i = 0; i < iPtnNum; i++)
......@@ -439,18 +436,14 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgno
taPoints[i].bValid = true;
taPoints[i].dE = std::pow(calcDist(taPoints[i], tpCircle) - tpCircle.dR, 2);
}
//排序
std::sort(taPoints, taPoints + iPtnNum, std::less<EyemOcsDXY2D>());
std::sort(taPoints.begin(), taPoints.end(), std::less<EyemOcsDXY2D>());
//忽略的点
for (int i = (iPtnNum - numToIgnore); i < iPtnNum; i++)
for (int i = iPtnNum - numToIgnore; i < iPtnNum; i++)
{
taPoints[i].bValid = false;
}
/*Run again...*/
fitCircle2D(iPtnNum, taPoints, iCalcMode, tpCircle);
fitCircle2D_wods(iPtnNum, &taPoints[0], tpCircle);
//计算RMS
for (int i = 0; i < iPtnNum; i++)
{
......@@ -460,19 +453,12 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgno
sr += r;
}
}
err = std::sqrt(sr / (double)(iPtnNum - numToIgnore));
if (err < EPS)
rms = std::sqrt(sr / (double)(iPtnNum - numToIgnore));
if (rms < 0.03 || std::abs((RMS - rms)) < 1e-3) {
break;
if (std::abs(err - min_err) < EPS)
break;
min_err = err;
}
RMS = rms;
}
//free memory
delete[] taPoints;
taPoints = NULL;
return FUNC_OK;
}
......@@ -439,7 +439,7 @@ extern "C" {
EXPORTS int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgnore, EyemOcsDABC &tpLine);
EXPORTS int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, double dRobustCoef, EyemOcsDABC &tpLine);
EXPORTS int eyemFitPlane(int, EyemOcsDXYZ[], int, double, EyemOcsDABCD *);
EXPORTS int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgnore, EyemOcsDXYR &tpCircle);
EXPORTS int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, int numToIgnore, double &RMS, EyemOcsDXYR &tpCircle);
EXPORTS int eyemFitEllipse(int, EyemOcsDXY[], int, double, EyemOcsDXYLSQ *);
EXPORTS int eyemFitEllipseC(int, EyemOcsDXY[], int, double, double[]);
EXPORTS int eyemFitConics(int, EyemOcsDXY[], int, double, double[]);
......@@ -851,6 +851,7 @@ extern "C" {
EXPORTS int eyemDetectAndDecode(EyemImage tpImage, EyemRect tpRoi, const char *ccFileName, const char *ccCodeType, IntPtr *hObject, EyemBarCode **tpResult, int *ipNum, bool bUseNiBlack, int iBlockSize, const int iRangeC, int iSymbolMin, int iSymbolMax, double dScaleUpAndDown = 0.5, double dToleErr = 0.5, double dMinorStep = 1.0);
EXPORTS int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject, EyemBarCode **hResults, int *ipNum, EyemImage *tpDstImg);
EXPORTS int eyemInitNNDataCodeModel(const char *detectorConfigPath, const char *detectorModelPath, const char *superResolutionConfigPath, const char *superResolutionModelPath);
EXPORTS int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject, EyemBarCode **hResults, int *ipNum, EyemImage *tpDstImg);
EXPORTS bool eyemDetectAndDecodeFree(IntPtr hObject);
EXPORTS int eyemCountObject(EyemImage tpImage, EyemRect tpRoi, const char *fileName, double dOffset, int iMinArea, int iMaxArea, int iWinSize, LPSTR *lpszNumObj, EyemImage *tpDstImg);
EXPORTS int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, LPSTR *lpszNumObj, EyemImage *tpDstImg);
......@@ -866,6 +867,7 @@ extern "C" {
EXPORTS int eyemReleaseModel(IntPtr &hModelID);
EXPORTS int eyemTrackFeature(EyemImage tpPrevImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum, int *ipResults, EyemImage *tpDstImg);
EXPORTS int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois, int iRoiNum);
EXPORTS int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircle, bool bHighAccuracy = false);
EXPORTS int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg);
#ifdef __cplusplus
......
......@@ -165,7 +165,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="barcodeDetector.h" />
<ClInclude Include="eyemBarCode.h" />
<ClInclude Include="eyemDataCode.h" />
<ClInclude Include="eyemBin.h" />
<ClInclude Include="eyemCalib.h" />
<ClInclude Include="eyemClp2d.h" />
......@@ -180,12 +180,11 @@
<ClInclude Include="eyemSmooth.h" />
<ClInclude Include="nnDetector.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="superScale.h" />
<ClInclude Include="yoloWrapper.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="barcodeDetector.cpp" />
<ClCompile Include="eyemBarCode.cpp" />
<ClCompile Include="eyemDataCode.cpp" />
<ClCompile Include="eyemBin.cpp" />
<ClCompile Include="eyemCalib.cpp" />
<ClCompile Include="eyemCg.cpp" />
......@@ -203,7 +202,6 @@
<ClCompile Include="eyemSmooth.cpp" />
<ClCompile Include="nnDetector.cpp" />
<ClCompile Include="libopencv.cpp" />
<ClCompile Include="superScale.cpp" />
<ClCompile Include="yoloWrapper.cpp" />
</ItemGroup>
<ItemGroup>
......
......@@ -54,21 +54,18 @@
<ClInclude Include="eyemGeneric.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="eyemBarCode.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="yoloWrapper.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="superScale.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="nnDetector.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="barcodeDetector.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="eyemDataCode.h">
<Filter>源文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="eyemLib.cpp">
......@@ -116,15 +113,9 @@
<ClCompile Include="eyemGeneric.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="eyemBarCode.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="yoloWrapper.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="superScale.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="libopencv.cpp">
<Filter>源文件</Filter>
</ClCompile>
......@@ -134,6 +125,9 @@
<ClCompile Include="barcodeDetector.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="eyemDataCode.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="eyemLib.rc">
......
#include "nnDetector.h"
#include "yoloWrapper.h"
#include "superScale.h"
#include "barcodeDetector.h"
class NNDetector::Impl {
......@@ -8,7 +7,7 @@ public:
Impl() {}
~Impl() {}
//检测框
//目标检测
std::vector<cv::Rect> detect(const cv::Mat& img);
//二维码解码
......@@ -17,13 +16,14 @@ public:
//获取缩放列表
std::vector<float> getScaleList(const int width, const int height);
//nn_detector
std::shared_ptr<YoloWrapper> detector_;
//缩放图像
cv::Mat processImageScale(const cv::Mat &src, float scale);
//std::shared_ptr<BarcodeDetector> bardetector_;
//目标检测器
std::shared_ptr<YoloWrapper> detector_;
//超分辨率缩放
std::shared_ptr<SuperScale> super_resolution_model_;
//一维码检测
std::shared_ptr<BarcodeDetector> bardetector_;
};
NNDetector::NNDetector(const std::string & detector_config_path,
......@@ -34,20 +34,12 @@ NNDetector::NNDetector(const std::string & detector_config_path,
if (!detector_config_path.empty() && !detector_model_path.empty()) {
p->detector_ = std::make_shared<YoloWrapper>();
p->detector_->init(detector_config_path, detector_model_path);
//p->bardetector_ = std::make_shared<BarcodeDetector>();
}
else {
p->detector_ = NULL;
}
p->bardetector_ = std::make_shared<BarcodeDetector>();
//TODO:初始化超分辨率图像模型
if (!super_resolution_prototxt_path.empty() && !super_resolution_caffe_model_path.empty()) {
p->super_resolution_model_ = std::make_shared<SuperScale>();
p->super_resolution_model_->init(super_resolution_prototxt_path, super_resolution_caffe_model_path);
}
else {
p->super_resolution_model_ = NULL;
}
}
std::vector<std::string> NNDetector::detectAndDecode(cv::InputArray img, std::vector<cv::Rect> &points, std::vector<cv::Rect> &__points) {
......@@ -89,7 +81,6 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto
}
std::vector<std::string> decode_results;
//限定框,防止越界
cv::Rect limit(0, 0, img.cols, img.rows);
for (auto& bbox : bboxes) {
if (bbox.height > 1000 || bbox.width > 1000) {
continue;
......@@ -111,7 +102,7 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto
auto scale_list = getScaleList(cropped_img.cols, cropped_img.rows);
for (auto cur_scale : scale_list) {
cv::Mat scaled_img =
super_resolution_model_->processImageScale(cropped_img, cur_scale, false);
processImageScale(cropped_img, cur_scale);
std::string result;
//解码
std::vector<cv::Point> _points;
......@@ -134,9 +125,112 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto
return decode_results;
}
std::vector<std::string> NNDetector::detectAndDecodeBarcode(cv::InputArray img, cv::Mat &showMat, std::vector<cv::Point> &points) {
CV_Assert(!img.empty());
if (img.cols() <= 40 || img.rows() <= 40) {
return std::vector<std::string>();
}
cv::Mat input;
int incn = img.channels();
if (incn == 4) {
cv::cvtColor(img, input, cv::COLOR_BGRA2BGR);
}
else if (incn == 1) {
cv::cvtColor(img, input, cv::COLOR_GRAY2BGR);//根据配置支持三通道图像
}
else {
input = img.getMat();
}
//检测
std::vector<cv::Point> _points;
p->bardetector_->detect(input, _points);
//转单通道
cv::Mat input_gray;
cv::cvtColor(input, input_gray, cv::COLOR_BGR2GRAY);
//解码
std::vector<std::string> results;
if (!_points.empty()) {
for (int n = 0; n < _points.size(); n += 4)
{
std::vector<cv::Point> __points(_points.begin() + n, _points.begin() + n + 4);
//防止越界
cv::Rect box = cv::boundingRect(__points)&cv::Rect(0, 0, input.cols, input.rows);
//
cv::Mat _input = input_gray(box);
cv::Point _t = (__points[2] + __points[3]) / 2 - (__points[0] + __points[1]) / 2;
double t = atan2(_t.y, _t.x)*180.0 / CV_PI;
const int tckH = _input.rows, tckW = _input.cols;
int tckdW = cvRound((double)tckH * abs(sin(t * CV_PI / 180.)) + (double)tckW * abs(cos(t * CV_PI / 180.)));
int tckdH = cvRound(ceil((double)tckW * abs(sin(t * CV_PI / 180.)) + (double)tckH * abs(cos(t * CV_PI / 180.))));
//创建矩阵
cv::Mat matx23f(2, 3, CV_64F);
matx23f = cv::getRotationMatrix2D(cv::Point2f((float)tckW / 2.0f - 0.5f, (float)tckH / 2.0f - 0.5f), t, 1.0);
//由于旋转产生的偏移
matx23f.ptr<double>(0)[2] += (float)(tckdW - tckW) / 2.0;
matx23f.ptr<double>(1)[2] += (float)(tckdH - tckH) / 2.0;
//输出矩阵
float matx[6];
matx[0] = (float)matx23f.ptr<double>(0)[0]; matx[1] = (float)matx23f.ptr<double>(0)[1]; matx[2] = (float)matx23f.ptr<double>(0)[2];
matx[3] = (float)matx23f.ptr<double>(1)[0]; matx[4] = (float)matx23f.ptr<double>(1)[1]; matx[5] = (float)matx23f.ptr<double>(1)[2];
//仿射变换
cv::Mat __input;
cv::warpAffine(_input, __input, matx23f, cv::Size(tckdW, tckdH), cv::INTER_CUBIC, cv::BORDER_REPLICATE);
//计算变换后的点
for (auto&__point : __points) {
cv::Point pt(__point.x - box.x, __point.y - box.y);
__point.x = cvRound((float)pt.x*matx[0] + (float)pt.y*matx[1] + matx[2]);
__point.y = cvRound((float)pt.x*matx[3] + (float)pt.y*matx[4] + matx[5]);
}
auto scale_list = { 1.0f,2.0f };
for (auto cur_scale : scale_list) {
cv::Mat scaled_img =
p->processImageScale(__input(cv::boundingRect(__points)&cv::Rect(0, 0, __input.cols, input.rows)), cur_scale);
std::string result;
int iRet = decodeImage(scaled_img, result, true);
if (iRet != -1) {
//画图
cv::Point pt = cv::Point(box.tl() + box.br()) / 2;
cv::putText(input, result, pt, cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1);
//输出
points.push_back(pt);
results.push_back(result);
break;
}
}
}
}
p->bardetector_->drawBarcode(showMat, _points);
return results;
}
std::vector<float> NNDetector::Impl::getScaleList(const int width, const int height) {
if (width < 320 || height < 320) return{ 1.0, 2.0, 0.5 };
if (width < 640 && height < 640) return{ 1.0, 0.5 };
return{ 0.5, 1.0 };
}
cv::Mat NNDetector::Impl::processImageScale(const cv::Mat &src, float scale) {
cv::Mat sr = src;
if (scale == 1.0) {
return sr;
}
cv::resize(src, sr, cv::Size(), scale, scale, cv::INTER_CUBIC);
return sr;
}
......@@ -19,6 +19,8 @@ public:
std::vector<std::string> detectAndDecode(cv::InputArray img,
std::vector<cv::Rect> &points = std::vector<cv::Rect>(), std::vector<cv::Rect> &allpoints = std::vector<cv::Rect>());
std::vector<std::string> detectAndDecodeBarcode(cv::InputArray img, cv::Mat &showMat, std::vector<cv::Point> &points = std::vector<cv::Point>());
std::mutex _mtx;
protected:
......
#include "superScale.h"
#define CLIP(x, x1, x2) cv::max(x1, cv::min(x, x2))
int SuperScale::init(const std::string &proto_path, const std::string &model_path) {
srnet_ = cv::dnn::readNetFromCaffe(proto_path, model_path);
net_loaded_ = true;
return 0;
}
cv::Mat SuperScale::processImageScale(const cv::Mat &src, float scale, const bool &use_sr,
int sr_max_size) {
cv::Mat dst = src;
if (scale == 1.0) { // src
return dst;
}
int width = src.cols;
int height = src.rows;
if (scale == 2.0) { // upsample
int SR_TH = sr_max_size;
if (use_sr && (int)sqrt(width * height * 1.0) < SR_TH && net_loaded_) {
int ret = superResoutionScale(src, dst);
if (ret == 0) return dst;
}
{ resize(src, dst, cv::Size(), scale, scale, cv::INTER_CUBIC); }
}
else if (scale < 1.0) { // downsample
resize(src, dst, cv::Size(), scale, scale, cv::INTER_AREA);
}
return dst;
}
int SuperScale::superResoutionScale(const cv::Mat &src, cv::Mat &dst) {
cv::Mat blob;
cv::dnn::blobFromImage(src, blob, 1.0 / 255, cv::Size(src.cols, src.rows), { 0.0f }, false, false);
srnet_.setInput(blob);
auto prob = srnet_.forward();
dst = cv::Mat(prob.size[2], prob.size[3], CV_8UC1);
for (int row = 0; row < prob.size[2]; row++) {
const float *prob_score = prob.ptr<float>(0, 0, row);
for (int col = 0; col < prob.size[3]; col++) {
float pixel = prob_score[col] * 255.0f;
dst.at<uint8_t>(row, col) = static_cast<uint8_t>(CLIP(pixel, 0.0f, 255.0f));
}
}
return 0;
}
\ No newline at end of file
#ifndef __SCALE_SUPER_SCALE_H_
#define __SCALE_SUPER_SCALE_H_
#include <stdio.h>
#include "opencv2/dnn.hpp"
#include "opencv2/imgproc.hpp"
class SuperScale {
public:
SuperScale() {};
~SuperScale() {};
int init(const std::string &proto_path, const std::string &model_path);
cv::Mat processImageScale(const cv::Mat &src, float scale, const bool &use_sr, int sr_max_size = 160);
private:
cv::dnn::Net srnet_;
bool net_loaded_ = false;
int superResoutionScale(const cv::Mat &src, cv::Mat &dst);
};
#endif // __SCALE_SUPER_SCALE_H_
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!