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">
......
......@@ -6388,20 +6388,181 @@ int eyemAOIForTSAV(EyemImage tpRefImg, EyemImage tpNextImg, EyemRect3 *tpRois, i
return FUNC_OK;
}
int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
int eyemMarkerTracing(EyemImage tpImage, double dThreshold, EyemOcsFXYR *tpCircle, bool bHighAccuracy)
{
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() > 3) {
const int X = image.cols; const int Y = image.rows;
int incn = image.channels();
if (incn > 3) {
cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
}
else if (incn == 1) {
cv::cvtColor(image, image, cv::COLOR_GRAY2BGR);
}
//图像备份
cv::Mat backup;
backup = image.clone();
//归一化
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range range)->void {
for (int y = range.start; y < range.end; y++) {
for (int x = 0; x < X; x++) {
uint8_t b, g, r;
float bgr = (float)(image.ptr<cv::Vec3b>(y)[x][0] + image.ptr<cv::Vec3b>(y)[x][1] + image.ptr<cv::Vec3b>(y)[x][2]);
bgr = bgr == 0 ? 1 : 1.0f / bgr;
b = cvRound(255.0f*(float)image.ptr<cv::Vec3b>(y)[x][0] * bgr);
g = cvRound(255.0f*(float)image.ptr<cv::Vec3b>(y)[x][1] * bgr);
r = cvRound(255.0f*(float)image.ptr<cv::Vec3b>(y)[x][2] * bgr);
image.ptr<cv::Vec3b>(y)[x] = cv::Vec3b(b, g, r);
}
}
});
//通道分离
cv::Mat mask;
std::vector<cv::Mat> mv;
cv::split(image, mv);
cv::threshold(mv[2], mask, dThreshold, 255, cv::THRESH_BINARY);
//去掉干扰
cv::morphologyEx(mask, mask, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7)));
std::vector<std::vector<cv::Point>> contours, contourfilter;
cv::findContours(mask, contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
//过滤
std::vector<cv::Point> approx;
for (auto&contour : contours) {
float arcL = (float)cv::arcLength(cv::Mat(contour), true);
cv::approxPolyDP(cv::Mat(contour), approx, arcL*0.01, true);
if (approx.size() > 10) {
cv::Rect bbox = cv::boundingRect(contour);
if (cv::max(bbox.width, bbox.height) > 20 && ((float)bbox.width / (float)bbox.height) > 0.85 && \
((float)bbox.width / (float)bbox.height) < 1.15) {
//圆度
double afa = 4.0f*CV_PI*cv::contourArea(contour, false) / std::pow(arcL, 2);
if (afa > 0.85) {
contourfilter.push_back(contour);
}
}
}
}
struct AFA {
double dMatchDeg;
EyemOcsDXYR tpCircle;
AFA() {};
AFA(double dMatchDeg, EyemOcsDXYR tpCircle) :dMatchDeg(dMatchDeg), tpCircle(tpCircle) {};
bool operator >(const AFA &te)const
{
return dMatchDeg > te.dMatchDeg;
}
bool operator <(const AFA &te)const
{
return dMatchDeg < te.dMatchDeg;
}
};
std::vector<AFA> afas;
//画图
for (auto&contour : contourfilter) {
std::vector<EyemOcsDXY> taPoints;
for (int n = 0; n < contour.size(); n++) {
EyemOcsDXY taPoint;
taPoint.dX = (double)contour[n].x;
taPoint.dY = (double)contour[n].y;
taPoints.push_back(taPoint);
}
double min_err;
EyemOcsDXYR _tpCircle;
eyemFitCircle((int)taPoints.size(), &taPoints[0], 0, 15, min_err, _tpCircle);
afas.push_back(AFA(min_err, _tpCircle));
}
if (afas.empty()) {
return FUNC_FAILED_DETECT;
}
//排序
std::sort(afas.begin(), afas.end(), std::less<AFA>());
//输出
tpCircle->fX = (float)afas[0].tpCircle.dX;
tpCircle->fY = (float)afas[0].tpCircle.dY;
tpCircle->fR = (float)afas[0].tpCircle.dR;
//#ifdef _DEBUG
// cv::circle(backup, cv::Point(tpCircle->fX, tpCircle->fY), tpCircle->fR, cv::Scalar(0, 255, 0));
//#endif
return FUNC_OK;
}
int eyemLibImpl(EyemImage tpImage, 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;
const int X = image.cols; const int Y = image.rows;
if (image.channels() > 3) {
cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
}
//原图备份
cv::Mat backup;
backup = image.clone();
//转float类型
cv::Mat imageF;
image.convertTo(imageF, CV_32F);
//归一化
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range range)->void {
for (int y = range.start; y < range.end; y++) {
for (int x = 0; x < X; x++) {
float b, g, r, bgr;
bgr = imageF.ptr<cv::Vec3f>(y)[x][0] + imageF.ptr<cv::Vec3f>(y)[x][1] + imageF.ptr<cv::Vec3f>(y)[x][2];
bgr = bgr == 0 ? 1 : bgr;
b = imageF.ptr<cv::Vec3f>(y)[x][0] / bgr;
g = imageF.ptr<cv::Vec3f>(y)[x][1] / bgr;
r = imageF.ptr<cv::Vec3f>(y)[x][2] / bgr;
imageF.ptr<cv::Vec3f>(y)[x] = cv::Vec3f(b, g, r);
}
}
});
//转int8类型
imageF.convertTo(image, CV_8U, 255);
////转hsv空间
//cv::cvtColor(backup, imageF, cv::COLOR_BGR2HSV);
cv::Mat mask;
//cv::inRange(imageF, cv::Scalar(166, 100, 100), cv::Scalar(186, 255, 255), mask);
//cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range range)->void {
// for (int y = range.start; y < range.end; y++) {
// for (int x = 0; x < X; x++) {
// float h, s, v;
// h = imageF.ptr<cv::Vec3b>(y)[x][0];
// if (!((h > 0 && h < 20) || (h > 150 && h < 255))) {
// imageF.ptr<cv::Vec3b>(y)[x][0] = 0;
// imageF.ptr<cv::Vec3b>(y)[x][1] = 0;
// imageF.ptr<cv::Vec3b>(y)[x][2] = 0;
// }
// }
// }
//});
std::vector<cv::Mat> mv;
cv::split(image, mv);
cv::threshold(mv[2], mask, 130, 255, cv::THRESH_BINARY);
cv::morphologyEx(mask, mask, cv::MORPH_OPEN, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7)));
#pragma region resize img
//const int minInputSize = 832;
......@@ -6439,123 +6600,122 @@ int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
#pragma region darknet
//加载类名
std::vector<std::string> classes;
std::string classFile = ".\\darknet\\detect.names";
////加载类名
//std::vector<std::string> classes;
//std::string classFile = ".\\darknet\\detect.names";
std::ifstream ifs(classFile.c_str());
//std::ifstream ifs(classFile.c_str());
std::string line;
while (std::getline(ifs, line)) classes.push_back(line);
//std::string line;
//while (std::getline(ifs, line)) classes.push_back(line);
//加载网络
cv::dnn::Net net = cv::dnn::readNet(".\\darknet\\yolov3-detect-tiny.cfg", ".\\darknet\\yolov3-detect-tiny_last.weights");
net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
net.setPreferableBackend(cv::dnn::DNN_TARGET_CPU);
////加载网络
//cv::dnn::Net net = cv::dnn::readNet(".\\darknet\\yolov3-detect-tiny.cfg", ".\\darknet\\yolov3-detect-tiny_last.weights");
//net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
//net.setPreferableBackend(cv::dnn::DNN_TARGET_CPU);
//获取输出层名称
auto layerNames = net.getLayerNames();
////获取输出层名称
//auto layerNames = net.getLayerNames();
std::vector<int> outLayers = net.getUnconnectedOutLayers();
//std::vector<int> outLayers = net.getUnconnectedOutLayers();
std::vector<std::string> outBlobNames(outLayers.size());
for (int i = 0; i < outLayers.size(); i++) {
outBlobNames[i] = layerNames[outLayers[i] - 1];
}
//std::vector<std::string> outBlobNames(outLayers.size());
//for (int i = 0; i < outLayers.size(); i++) {
// outBlobNames[i] = layerNames[outLayers[i] - 1];
//}
//预处理图像
cv::Mat blob;
cv::dnn::blobFromImage(image, blob, 1 / 255., cv::Size(608, 608));
////预处理图像
//cv::Mat blob;
//cv::dnn::blobFromImage(image, blob, 1 / 255., cv::Size(608, 608));
//为网络输入新值
net.setInput(blob);
////为网络输入新值
//net.setInput(blob);
//获取预测结果
std::vector<cv::Mat> outputBlobs;
net.forward(outputBlobs, outBlobNames);
////获取预测结果
//std::vector<cv::Mat> outputBlobs;
//net.forward(outputBlobs, outBlobNames);
std::vector<int> classIds;//储存识别类的索引
std::vector<float> confidences;//储存置信度
std::vector<cv::Rect> bboxes;//储存边框
//std::vector<int> classIds;//储存识别类的索引
//std::vector<float> confidences;//储存置信度
//std::vector<cv::Rect> bboxes;//储存边框
for (int n = 0; n < outputBlobs.size(); n++) {
for (int row = 0; row < outputBlobs[n].rows; row++) {
//置信度
cv::Mat prob = outputBlobs[n](cv::Range(row, row + 1), cv::Range(5, outputBlobs[n].cols));
//for (int n = 0; n < outputBlobs.size(); n++) {
// for (int row = 0; row < outputBlobs[n].rows; row++) {
// //置信度
// cv::Mat prob = outputBlobs[n](cv::Range(row, row + 1), cv::Range(5, outputBlobs[n].cols));
double confidence;
cv::Point classIdPoint;
// double confidence;
// cv::Point classIdPoint;
//取得最大分数值与索引
cv::minMaxLoc(prob, 0, &confidence, 0, &classIdPoint);
//如果置信度大于阈值
if (confidence > 0.01) {
// //取得最大分数值与索引
// cv::minMaxLoc(prob, 0, &confidence, 0, &classIdPoint);
// //如果置信度大于阈值
// if (confidence > 0.01) {
cv::Mat dt = outputBlobs[n];
// cv::Mat dt = outputBlobs[n];
cv::Mat x = outputBlobs[n](cv::Range(row, row + 1), cv::Range(0, 5));
// cv::Mat x = outputBlobs[n](cv::Range(row, row + 1), cv::Range(0, 5));
int cx = cvRound(x.ptr<float>(0)[0] * (float)image.cols);
int cy = cvRound(x.ptr<float>(0)[1] * (float)image.rows);
int w = cvRound(x.ptr<float>(0)[2] * (float)image.cols);
int h = cvRound(x.ptr<float>(0)[3] * (float)image.rows);
// int cx = cvRound(x.ptr<float>(0)[0] * (float)image.cols);
// int cy = cvRound(x.ptr<float>(0)[1] * (float)image.rows);
// int w = cvRound(x.ptr<float>(0)[2] * (float)image.cols);
// int h = cvRound(x.ptr<float>(0)[3] * (float)image.rows);
int left = cx - w / 2;
int top = cy - h / 2;
// int left = cx - w / 2;
// int top = cy - h / 2;
classIds.push_back(classIdPoint.x);
confidences.push_back((float)confidence);
bboxes.push_back(cv::Rect(left, top, w, h));
}
}
}
// classIds.push_back(classIdPoint.x);
// confidences.push_back((float)confidence);
// bboxes.push_back(cv::Rect(left, top, w, h));
// }
// }
//}
//cv::Mat showMat;
//cv::cvtColor(image)
////cv::Mat showMat;
////cv::cvtColor(image)
std::vector<int> indices;
//非极大值抑制
cv::dnn::NMSBoxes(bboxes, confidences, 0.01f, 0.05f, indices);
//std::vector<int> indices;
////非极大值抑制
//cv::dnn::NMSBoxes(bboxes, confidences, 0.01f, 0.05f, indices);
for (int i = 0; i < indices.size(); i++) {
int idx = indices[i];
cv::Rect bbox = bboxes[idx] & cv::Rect(0, 0, image.cols, image.rows);
//标签
std::string label = cv::format("%.2f", confidences[idx]);
//for (int i = 0; i < indices.size(); i++) {
// int idx = indices[i];
// cv::Rect bbox = bboxes[idx] & cv::Rect(0, 0, image.cols, image.rows);
// //标签
// std::string label = cv::format("%.2f", confidences[idx]);
if (!classes.empty()) {
label = classes[classIds[idx]] + ":" + label;
}
// if (!classes.empty()) {
// label = classes[classIds[idx]] + ":" + label;
// }
int baseLine;
cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
// int baseLine;
// cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
cv::Scalar pal(0, 255, 0);
// cv::Scalar pal(0, 255, 0);
cv::rectangle(image, bbox, pal);
cv::rectangle(image, cv::Point(bbox.x, bbox.y - labelSize.height - baseLine), cv::Point(bbox.x + labelSize.width, bbox.y), pal, cv::FILLED);
cv::putText(image, label, cv::Point(bbox.tl().x, bbox.tl().y - baseLine), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1);
}
// cv::rectangle(image, bbox, pal);
// cv::rectangle(image, cv::Point(bbox.x, bbox.y - labelSize.height - baseLine), cv::Point(bbox.x + labelSize.width, bbox.y), pal, cv::FILLED);
// cv::putText(image, label, cv::Point(bbox.tl().x, bbox.tl().y - baseLine), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1);
//}
///<输出计数结果标记图像
{
tpDstImg->iWidth = image.cols; tpDstImg->iHeight = image.rows; tpDstImg->iDepth = image.depth(); tpDstImg->iChannels = image.channels();
/////<输出计数结果标记图像
//{
// tpDstImg->iWidth = image.cols; tpDstImg->iHeight = image.rows; tpDstImg->iDepth = image.depth(); tpDstImg->iChannels = image.channels();
//内存尺寸
int _Size = tpDstImg->iWidth*tpDstImg->iHeight*tpDstImg->iChannels * sizeof(uint8_t);
// //内存尺寸
// 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);
// //分配初始化内存
// tpDstImg->vpImage = (uint8_t *)malloc(_Size);
// if (NULL == tpDstImg->vpImage)
// return FUNC_NOT_ENOUGH_MEM;
// memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据
memcpy(tpDstImg->vpImage, image.data, _Size);
}
// //拷贝数据
// memcpy(tpDstImg->vpImage, image.data, _Size);
//}
#pragma endregion
return FUNC_OK;
}
#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!