Commit 5d868695 张士柳

1 个父辈 c28b0fea
...@@ -6,6 +6,7 @@ using System.Collections.Generic; ...@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Threading; using System.Threading;
using System.IO;
namespace eyemLib_Sharp namespace eyemLib_Sharp
{ {
...@@ -342,6 +343,14 @@ namespace eyemLib_Sharp ...@@ -342,6 +343,14 @@ namespace eyemLib_Sharp
public double dVar; // 某种可能会使用的值 public double dVar; // 某种可能会使用的值
} }
[StructLayout(LayoutKind.Sequential)]
public struct BboxContainer
{
//最多支持100个目标
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)]
public EyemRect[] bboxes;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Orthogonal Coordinate System // Orthogonal Coordinate System
...@@ -1020,6 +1029,25 @@ namespace eyemLib_Sharp ...@@ -1020,6 +1029,25 @@ namespace eyemLib_Sharp
private static extern int eyemClp2dTangentPointToCircle(EyemOcsDXY tpPoint, EyemOcsDXYR tpCircle, ref EyemOcsDABC tpTangent1, ref EyemOcsDXY tpContact1, ref EyemOcsDABC tpTangent2, ref EyemOcsDXY tpContact2); private static extern int eyemClp2dTangentPointToCircle(EyemOcsDXY tpPoint, EyemOcsDXYR tpCircle, ref EyemOcsDABC tpTangent1, ref EyemOcsDXY tpContact1, ref EyemOcsDABC tpTangent2, ref EyemOcsDXY tpContact2);
#endregion #endregion
#region 深度学习目标检测器
/// <summary>
/// 初始化检测器
/// </summary>
/// <param name="detectorConfigPath">配置文件</param>
/// <param name="detectorModelPath">模型文件</param>
/// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemInitNNDetector(string detectorConfigPath, string detectorModelPath);
/// <summary>
/// 目标检测器
/// </summary>
/// <param name="tpImage">输入图像</param>
/// <returns></returns>
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
private static extern int eyemNNDetector(EyemImage tpImage, out int ipNum, ref BboxContainer container);
#endregion
#region 项目 #region 项目
//普通器件(仍采用旧的算法) //普通器件(仍采用旧的算法)
[DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)] [DllImport("eyemLib.dll", CharSet = CharSet.None, CallingConvention = CallingConvention.Cdecl)]
...@@ -1356,6 +1384,14 @@ namespace eyemLib_Sharp ...@@ -1356,6 +1384,14 @@ namespace eyemLib_Sharp
//eyemEdgesPixel(ucpImage, 15); //eyemEdgesPixel(ucpImage, 15);
#endregion #endregion
#region Test NNDetector
//eyemInitNNDetector(".\\darknet\\detect-tiny-label.cfg", ".\\darknet\\detect-tiny-label.weights");
//int ipNum = 0;
//BboxContainer container = new BboxContainer();
//eyemNNDetector(image, out ipNum, ref container);
#endregion
EyemRect tpRoi = new EyemRect(); EyemRect tpRoi = new EyemRect();
tpRoi.iXs = 200; tpRoi.iYs = 150; tpRoi.iXs = 200; tpRoi.iYs = 150;
...@@ -1700,6 +1736,44 @@ namespace eyemLib_Sharp ...@@ -1700,6 +1736,44 @@ namespace eyemLib_Sharp
eyemImageFree(ref image); eyemImageFree(ref image);
} }
#region 文件重新命名
public static void eyemRenameFile(string filePath)
{
List<string> fileNames = new List<string>();
getAllFiles(filePath, ref fileNames);
//批量重命名
for (int index = 0; index < fileNames.Count; index++)
{
string destFileNmae = "D://标签识别//" + index.ToString().PadLeft(5, '0') + ".png";
File.Move(fileNames[index], destFileNmae);
}
}
static void getAllFiles(string filePath, ref List<string> fileNames)
{
getDirectory(filePath, ref fileNames);
}
public static void getFileName(string path, ref List<string> fileNames)
{
DirectoryInfo root = new DirectoryInfo(path);
foreach (FileInfo f in root.GetFiles())
{
fileNames.Add(f.FullName);
}
}
public static void getDirectory(string path, ref List<string> fileNames)
{
getFileName(path, ref fileNames);
DirectoryInfo root = new DirectoryInfo(path);
foreach (DirectoryInfo d in root.GetDirectories())
{
getDirectory(d.FullName, ref fileNames);
}
}
#endregion
#region EyemImageBitmap相互转换 #region EyemImageBitmap相互转换
public static Bitmap eyemCvtToBitmap(EyemImage tpImage) public static Bitmap eyemCvtToBitmap(EyemImage tpImage)
{ {
......
...@@ -16,6 +16,8 @@ namespace eyemLib_Sharp ...@@ -16,6 +16,8 @@ namespace eyemLib_Sharp
di.Create(); di.Create();
} }
//EyemLib.eyemRenameFile(@"D:\新建文件夹");
//初始化 //初始化
EyemLib.Init(); EyemLib.Init();
......
...@@ -987,30 +987,24 @@ static double getThreshVal_Otsu_8u(const cv::Mat& _src) ...@@ -987,30 +987,24 @@ static double getThreshVal_Otsu_8u(const cv::Mat& _src)
int eyemBinThreshold(EyemImage tpSrcImg, int iLightDark, double dThresh, double dMaxVal, EyemImage *tpDstImg) int eyemBinThreshold(EyemImage tpSrcImg, int iLightDark, double dThresh, double dMaxVal, EyemImage *tpDstImg)
{ {
cv::Mat image = cv::Mat(tpSrcImg.iHeight, tpSrcImg.iWidth, MAKETYPE(tpSrcImg.iDepth, tpSrcImg.iChannels), tpSrcImg.vpImage).clone(); cv::Mat image = cv::Mat(tpSrcImg.iHeight, tpSrcImg.iWidth, MAKETYPE(tpSrcImg.iDepth, tpSrcImg.iChannels), tpSrcImg.vpImage).clone();
if (image.empty()) { if (image.empty()) {
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
} }
cv::Mat binary; cv::Mat binary;
//执行二值化操作 //执行二值化操作
cv::threshold(image, binary, dThresh, dMaxVal, iLightDark); cv::threshold(image, binary, dThresh, dMaxVal, iLightDark);
//输出结果图像
{
tpDstImg->iWidth = binary.cols; tpDstImg->iHeight = binary.rows; tpDstImg->iDepth = binary.depth(); tpDstImg->iChannels = binary.channels(); tpDstImg->iWidth = binary.cols; tpDstImg->iHeight = binary.rows; tpDstImg->iDepth = binary.depth(); tpDstImg->iChannels = binary.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); tpDstImg->vpImage = (uint8_t *)malloc(_Size);
if (NULL == tpDstImg->vpImage) if (NULL == tpDstImg->vpImage)
return FUNC_NOT_ENOUGH_MEM; return FUNC_NOT_ENOUGH_MEM;
memset(tpDstImg->vpImage, 0, _Size); memset(tpDstImg->vpImage, 0, _Size);
//拷贝数据 //拷贝数据
memcpy(tpDstImg->vpImage, binary.data, _Size); memcpy(tpDstImg->vpImage, binary.data, _Size);
}
return FUNC_OK; return FUNC_OK;
} }
...@@ -1272,7 +1266,7 @@ int eyemBinClosing(EyemImage tpSrcImg, int iBinLevel, int iNum, EyemImage *tpDst ...@@ -1272,7 +1266,7 @@ int eyemBinClosing(EyemImage tpSrcImg, int iBinLevel, int iNum, EyemImage *tpDst
int eyemBinBlob(EyemImage tpImage, IntPtr *hObject, int iAreaThrs, EyemBinBlob **tpResult, int *ipNum, EyemImage *tpDstImg) int eyemBinBlob(EyemImage tpImage, IntPtr *hObject, int iAreaThrs, EyemBinBlob **tpResult, int *ipNum, EyemImage *tpDstImg)
{ {
cv::Mat image(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage); cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
if (image.empty()) { if (image.empty()) {
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
......
...@@ -126,13 +126,14 @@ void eyemClp2dAreaTriangle(EyemOcsDXY tpPoint1, EyemOcsDXY tpPoint2, EyemOcsDXY ...@@ -126,13 +126,14 @@ void eyemClp2dAreaTriangle(EyemOcsDXY tpPoint1, EyemOcsDXY tpPoint2, EyemOcsDXY
int eyemClp2dCircleThreePoints(EyemOcsDXY tpPoint1, EyemOcsDXY tpPoint2, EyemOcsDXY tpPoint3, EyemOcsDXYR &tpCircle) int eyemClp2dCircleThreePoints(EyemOcsDXY tpPoint1, EyemOcsDXY tpPoint2, EyemOcsDXY tpPoint3, EyemOcsDXYR &tpCircle)
{ {
//计算系数 //计算系数
double sa[9], sb[3]; 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); cv::Mat a = cv::Mat(3, 3, CV_64F, sa), b = cv::Mat(3, 1, CV_64F, sb);
//系数矩阵A*X=B; //系数矩阵A*X=B;
cv::Mat x = cv::Mat(3, 1, CV_64F); cv::Mat x = cv::Mat(3, 1, CV_64F, sx);
std::memset(sa, 0, sizeof(sa)); std::memset(sa, 0, sizeof(sa));
std::memset(sb, 0, sizeof(sb)); std::memset(sb, 0, sizeof(sb));
std::memset(sx, 0, sizeof(sx));
sa[0] = -2.0*tpPoint1.dX, sa[1] = -2.0*tpPoint1.dY, sa[2] = 1.; sa[0] = -2.0*tpPoint1.dX, sa[1] = -2.0*tpPoint1.dY, sa[2] = 1.;
sa[3] = -2.0*tpPoint2.dX, sa[4] = -2.0*tpPoint2.dY, sa[5] = 1.; sa[3] = -2.0*tpPoint2.dX, sa[4] = -2.0*tpPoint2.dY, sa[5] = 1.;
...@@ -144,9 +145,9 @@ int eyemClp2dCircleThreePoints(EyemOcsDXY tpPoint1, EyemOcsDXY tpPoint2, EyemOcs ...@@ -144,9 +145,9 @@ int eyemClp2dCircleThreePoints(EyemOcsDXY tpPoint1, EyemOcsDXY tpPoint2, EyemOcs
//solve //solve
cv::solve(a, b, x, cv::DECOMP_SVD); cv::solve(a, b, x, cv::DECOMP_SVD);
tpCircle.dX = x.ptr<double>(0)[0]; tpCircle.dX = sx[0];
tpCircle.dY = x.ptr<double>(1)[0]; tpCircle.dY = sx[1];
tpCircle.dR = sqrt(pow(x.ptr<double>(0)[0], 2) + pow(x.ptr<double>(1)[0], 2) - (x.ptr<double>(2)[0])); tpCircle.dR = sqrt(pow(sx[0], 2) + pow(sx[1], 2) - (sx[2]));
return FUNC_OK; return FUNC_OK;
} }
......
#include "nnDetector.h" #include "eyemCodeDetector.h"
#include "yoloWrapper.h" #include "yoloWrapper.h"
#include "barcodeDetector.h" #include "barcodeDetector.h"
class NNDetector::Impl { class CodeDetector::Impl {
public: public:
Impl() {} Impl() {}
~Impl() {} ~Impl() {}
...@@ -26,11 +26,11 @@ public: ...@@ -26,11 +26,11 @@ public:
std::shared_ptr<BarcodeDetector> bardetector_; std::shared_ptr<BarcodeDetector> bardetector_;
}; };
NNDetector::NNDetector(const std::string & detector_config_path, CodeDetector::CodeDetector(const std::string & detector_config_path,
const std::string & detector_model_path, const std::string & detector_model_path,
const std::string & super_resolution_prototxt_path, const std::string & super_resolution_prototxt_path,
const std::string & super_resolution_caffe_model_path) { const std::string & super_resolution_caffe_model_path) {
p = cv::makePtr<NNDetector::Impl>(); p = cv::makePtr<CodeDetector::Impl>();
if (!detector_config_path.empty() && !detector_model_path.empty()) { if (!detector_config_path.empty() && !detector_model_path.empty()) {
p->detector_ = std::make_shared<YoloWrapper>(); p->detector_ = std::make_shared<YoloWrapper>();
p->detector_->init(detector_config_path, detector_model_path); p->detector_->init(detector_config_path, detector_model_path);
...@@ -42,7 +42,7 @@ NNDetector::NNDetector(const std::string & detector_config_path, ...@@ -42,7 +42,7 @@ NNDetector::NNDetector(const std::string & detector_config_path,
//TODO:初始化超分辨率图像模型 //TODO:初始化超分辨率图像模型
} }
std::vector<std::string> NNDetector::detectAndDecode(cv::InputArray img, std::vector<cv::Rect> &points, std::vector<cv::Rect> &__points) { std::vector<std::string> CodeDetector::detectAndDecode(cv::InputArray img, std::vector<cv::Rect> &points, std::vector<cv::Rect> &__points) {
CV_Assert(!img.empty()); CV_Assert(!img.empty());
if (img.cols() <= 20 || img.rows() <= 20) { if (img.cols() <= 20 || img.rows() <= 20) {
...@@ -78,11 +78,11 @@ std::vector<std::string> NNDetector::detectAndDecode(cv::InputArray img, std::ve ...@@ -78,11 +78,11 @@ std::vector<std::string> NNDetector::detectAndDecode(cv::InputArray img, std::ve
return results; return results;
} }
std::vector<cv::Rect> NNDetector::Impl::detect(const cv::Mat& img) { std::vector<cv::Rect> CodeDetector::Impl::detect(const cv::Mat& img) {
return detector_->forward(img); return detector_->forward(img);
} }
std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vector<cv::Rect>& bboxes, std::vector<cv::Rect>& points) { std::vector<std::string> CodeDetector::Impl::decode(const cv::Mat& img, std::vector<cv::Rect>& bboxes, std::vector<cv::Rect>& points) {
if (bboxes.size() == 0) { if (bboxes.size() == 0) {
logger.t("__eyemDetectAndDecodeUseNN__detectAndDecode__decode__:未识别到二维码"); logger.t("__eyemDetectAndDecodeUseNN__detectAndDecode__decode__:未识别到二维码");
return std::vector<std::string>(); return std::vector<std::string>();
...@@ -138,7 +138,7 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto ...@@ -138,7 +138,7 @@ std::vector<std::string> NNDetector::Impl::decode(const cv::Mat& img, std::vecto
return decode_results; return decode_results;
} }
std::vector<std::string> NNDetector::detectAndDecodeBarcode(cv::InputArray img, cv::Mat &showMat, std::vector<cv::Point> &points) { std::vector<std::string> CodeDetector::detectAndDecodeBarcode(cv::InputArray img, cv::Mat &showMat, std::vector<cv::Point> &points) {
CV_Assert(!img.empty()); CV_Assert(!img.empty());
...@@ -230,13 +230,13 @@ std::vector<std::string> NNDetector::detectAndDecodeBarcode(cv::InputArray img, ...@@ -230,13 +230,13 @@ std::vector<std::string> NNDetector::detectAndDecodeBarcode(cv::InputArray img,
return results; return results;
} }
std::vector<float> NNDetector::Impl::getScaleList(const int width, const int height) { std::vector<float> CodeDetector::Impl::getScaleList(const int width, const int height) {
if (width < 320 || height < 320) return{ 1.0, 2.0, 0.5 }; if (width < 320 || height < 320) return{ 1.0, 2.0, 0.5 };
if (width < 640 && height < 640) return{ 1.0, 0.5 }; if (width < 640 && height < 640) return{ 1.0, 0.5 };
return{ 0.5, 1.0 }; return{ 0.5, 1.0 };
} }
cv::Mat NNDetector::Impl::processImageScale(const cv::Mat &src, float scale) { cv::Mat CodeDetector::Impl::processImageScale(const cv::Mat &src, float scale) {
cv::Mat sr = src; cv::Mat sr = src;
if (scale == 1.0) { if (scale == 1.0) {
return sr; return sr;
......
#pragma once #pragma once
// //
// detectAndDecode2d¡¤±êÍ· // eyemCodeDetector¡¤±êÍ·
// //
#ifndef __NNDETECTOR_H #ifndef __EYEMCODEDETECTOR_H
#define __NNDETECTOR_H #define __EYEMCODEDETECTOR_H
#include "opencv2/core.hpp" #include "opencv2/core.hpp"
#include "libdecode.h" #include "libdecode.h"
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
extern Logger logger; extern Logger logger;
class NNDetector { class CodeDetector {
public: public:
NNDetector(const std::string& detector_config_path = "", CodeDetector(const std::string& detector_config_path = "",
const std::string& detector_model_path = "", const std::string& detector_model_path = "",
const std::string& super_resolution_config_path = "", const std::string& super_resolution_config_path = "",
const std::string& super_resolution_model_path = ""); const std::string& super_resolution_model_path = "");
NNDetector() {}; CodeDetector() {};
std::vector<std::string> detectAndDecode(cv::InputArray img, 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<cv::Rect> &points = std::vector<cv::Rect>(), std::vector<cv::Rect> &allpoints = std::vector<cv::Rect>());
...@@ -30,5 +30,5 @@ protected: ...@@ -30,5 +30,5 @@ protected:
class Impl; class Impl;
cv::Ptr<Impl> p; cv::Ptr<Impl> p;
}; };
#endif/* __NNDETECTOR_H */ #endif/* __EYEMCODEDETECTOR_H */
...@@ -522,7 +522,7 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject, ...@@ -522,7 +522,7 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject,
logger.t("__eyemDetectAndDecodeUseNN__:开始识别并解码二维码"); logger.t("__eyemDetectAndDecodeUseNN__:开始识别并解码二维码");
//识别并解码 //识别并解码
std::vector<cv::Rect> points; std::vector<cv::Rect> __points; std::vector<cv::Rect> points; std::vector<cv::Rect> __points;
auto results = detector->detectAndDecode(image, points, __points); auto results = pCodeDetector->detectAndDecode(image, points, __points);
#pragma region discard #pragma region discard
//if (image.channels() == 1) { //if (image.channels() == 1) {
...@@ -553,7 +553,7 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject, ...@@ -553,7 +553,7 @@ int eyemDetectAndDecodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *hObject,
// 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); // 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(); // tpDstImg->iWidth = showMat.cols; tpDstImg->iHeight = showMat.rows; tpDstImg->iDepth = showMat.depth(); tpDstImg->iChannels = showMat.channels();
...@@ -623,7 +623,7 @@ int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *h ...@@ -623,7 +623,7 @@ int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *h
cv::Mat showMat = image.clone(); cv::Mat showMat = image.clone();
//识别并解码 //识别并解码
std::vector<cv::Point> points; std::vector<cv::Point> points;
auto results = detector->detectAndDecodeBarcode(image, showMat, points); auto results = pCodeDetector->detectAndDecodeBarcode(image, showMat, points);
#pragma region discard #pragma region discard
...@@ -638,7 +638,7 @@ int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *h ...@@ -638,7 +638,7 @@ int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *h
// 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); // 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(); // tpDstImg->iWidth = showMat.cols; tpDstImg->iHeight = showMat.rows; tpDstImg->iDepth = showMat.depth(); tpDstImg->iChannels = showMat.channels();
...@@ -692,12 +692,10 @@ int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *h ...@@ -692,12 +692,10 @@ int eyemDetectAndDecodeBarcodeUseNN(EyemImage tpImage, EyemRect tpRoi, IntPtr *h
int eyemInitNNDataCodeModel(const char *detectorConfigPath, const char *detectorModelPath, const char *superResolutionConfigPath, const char *superResolutionModelPath) int eyemInitNNDataCodeModel(const char *detectorConfigPath, const char *detectorModelPath, const char *superResolutionConfigPath, const char *superResolutionModelPath)
{ {
try try {
{ pCodeDetector = cv::makePtr<CodeDetector>(detectorConfigPath, detectorModelPath, superResolutionConfigPath, superResolutionModelPath);
detector = cv::makePtr<NNDetector>(detectorConfigPath, detectorModelPath, superResolutionConfigPath, superResolutionModelPath);
} }
catch (const std::exception& e) catch (const std::exception& e) {
{
std::cout << e.what() << std::endl; std::cout << e.what() << std::endl;
return FUNC_CANNOT_CALC; return FUNC_CANNOT_CALC;
} }
......
...@@ -13,11 +13,11 @@ ...@@ -13,11 +13,11 @@
#endif #endif
#include "eyemLib.h" #include "eyemLib.h"
#include "nnDetector.h" #include "eyemCodeDetector.h"
std::mutex mtx; std::mutex mtx;
cv::Ptr<NNDetector> detector; cv::Ptr<CodeDetector> pCodeDetector;
extern Logger logger; extern Logger logger;
......
#include"eyemEdge.h" #include"eyemEdge.h"
void thinningIteration(cv::Mat& img, int iter) int eyemEdgesPixel(EyemImage tpImage, double dThreshold)
{ {
CV_Assert(img.channels() == 1); cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
CV_Assert(img.depth() != sizeof(uchar));
CV_Assert(img.rows > 3 && img.cols > 3);
cv::Mat marker = cv::Mat::zeros(img.size(), CV_8UC1);
int nRows = img.rows;
int nCols = img.cols;
if (img.isContinuous()) {
nCols *= nRows;
nRows = 1;
}
int x, y;
uchar *pAbove;
uchar *pCurr;
uchar *pBelow;
uchar *nw, *no, *ne; // north (pAbove)
uchar *we, *me, *ea;
uchar *sw, *so, *se; // south (pBelow)
uchar *pDst;
// initialize row pointers
pAbove = NULL;
pCurr = img.ptr<uchar>(0);
pBelow = img.ptr<uchar>(1);
for (y = 1; y < img.rows - 1; ++y) {
// shift the rows up by one
pAbove = pCurr;
pCurr = pBelow;
pBelow = img.ptr<uchar>(y + 1);
pDst = marker.ptr<uchar>(y);
// initialize col pointers
no = &(pAbove[0]);
ne = &(pAbove[1]);
me = &(pCurr[0]);
ea = &(pCurr[1]);
so = &(pBelow[0]);
se = &(pBelow[1]);
for (x = 1; x < img.cols - 1; ++x) {
// shift col pointers left by one (scan left to right)
nw = no;
no = ne;
ne = &(pAbove[x + 1]);
we = me;
me = ea;
ea = &(pCurr[x + 1]);
sw = so;
so = se;
se = &(pBelow[x + 1]);
int A = (*no == 0 && *ne == 1) + (*ne == 0 && *ea == 1) +
(*ea == 0 && *se == 1) + (*se == 0 && *so == 1) +
(*so == 0 && *sw == 1) + (*sw == 0 && *we == 1) +
(*we == 0 && *nw == 1) + (*nw == 0 && *no == 1);
int B = *no + *ne + *ea + *se + *so + *sw + *we + *nw;
int m1 = iter == 0 ? (*no * *ea * *so) : (*no * *ea * *we);
int m2 = iter == 0 ? (*ea * *so * *we) : (*no * *so * *we);
if (A == 1 && (B >= 2 && B <= 6) && m1 == 0 && m2 == 0)
pDst[x] = 1;
}
}
img &= ~marker;
}
static void thinning(const cv::Mat& src, cv::Mat& dst)
{
dst = src.clone();
dst /= 255; // convert to binary image
cv::Mat prev = cv::Mat::zeros(dst.size(), CV_8UC1);
cv::Mat diff;
do {
thinningIteration(dst, 0);
thinningIteration(dst, 1);
cv::absdiff(dst, prev, diff);
dst.copyTo(prev);
} while (cv::countNonZero(diff) > 0);
dst *= 255;
}
int eyemEdgesPixel(EyemImage tpImage, double dThresh)
{
cv::Mat image(tpImage.iHeight, tpImage.iWidth, CV_8UC1, tpImage.vpImage);
if (image.empty()) { if (image.empty()) {
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
} }
int X = image.cols, Y = image.rows; int X = image.cols, Y = image.rows;
uchar *upF = image.data; uchar *upF = image.data;
/*计算偏导*/ /*计算偏导*/
double *dpFx = (double *)malloc(X*Y * sizeof(double)); double *dpFx = (double *)malloc(X*Y * sizeof(double));
double *dpFy = (double *)malloc(X*Y * sizeof(double)); double *dpFy = (double *)malloc(X*Y * sizeof(double));
...@@ -111,10 +16,8 @@ int eyemEdgesPixel(EyemImage tpImage, double dThresh) ...@@ -111,10 +16,8 @@ int eyemEdgesPixel(EyemImage tpImage, double dThresh)
double *dpMag = (double *)malloc(X*Y * sizeof(double)); double *dpMag = (double *)malloc(X*Y * sizeof(double));
cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void { cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void {
for (int y = range.start; y < range.end; y++) for (int y = range.start; y < range.end; y++) {
{ for (int x = 1; x < X - 1; x++) {
for (int x = 1; x < X - 1; x++)
{
dpFx[(x)+(y)*X] = 0.5*((double)(upF[(x + 1) + (y)*X]) - (double)(upF[(x - 1) + (y)*X])); dpFx[(x)+(y)*X] = 0.5*((double)(upF[(x + 1) + (y)*X]) - (double)(upF[(x - 1) + (y)*X]));
dpFy[(x)+(y)*X] = 0.5*((double)(upF[(x)+(y + 1)*X]) - (double)(upF[(x)+(y - 1)*X])); dpFy[(x)+(y)*X] = 0.5*((double)(upF[(x)+(y + 1)*X]) - (double)(upF[(x)+(y - 1)*X]));
dpMag[(x)+(y)*X] = sqrt(dpFx[(x)+(y)*X] * dpFx[(x)+(y)*X] + dpFy[(x)+(y)*X] * dpFy[(x)+(y)*X]); dpMag[(x)+(y)*X] = sqrt(dpFx[(x)+(y)*X] * dpFx[(x)+(y)*X] + dpFy[(x)+(y)*X] * dpFy[(x)+(y)*X]);
...@@ -128,43 +31,34 @@ int eyemEdgesPixel(EyemImage tpImage, double dThresh) ...@@ -128,43 +31,34 @@ int eyemEdgesPixel(EyemImage tpImage, double dThresh)
cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void { cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void {
for (int y = range.start; y < range.end; y++) for (int y = range.start; y < range.end; y++)
for (int x = 1; x < (X - 1); x++) for (int x = 1; x < (X - 1); x++) {
{ if (dpMag[(x)+(y)*X] > dThreshold) {
if (dpMag[(x)+(y)*X] > dThresh)
{
//判断边缘 //判断边缘
if (abs(dpFy[(x)+(y)*X]) >= abs(dpFx[(x)+(y)*X]) && if (abs(dpFy[(x)+(y)*X]) >= abs(dpFx[(x)+(y)*X]) &&
abs(dpFy[(x)+(y)*X]) >= abs(dpFy[(x)+(y - 1)*X]) && abs(dpFy[(x)+(y)*X]) > abs(dpFy[(x)+(y + 1)*X])) abs(dpFy[(x)+(y)*X]) >= abs(dpFy[(x)+(y - 1)*X]) && abs(dpFy[(x)+(y)*X]) > abs(dpFy[(x)+(y + 1)*X])) {
{
ucpLabel[(x)+(y)*X] = 255;//垂直边缘-2 ucpLabel[(x)+(y)*X] = 255;//垂直边缘-2
} }
else if (abs(dpFx[(x)+(y)*X]) > abs(dpFy[(x)+(y)*X]) && else if (abs(dpFx[(x)+(y)*X]) > abs(dpFy[(x)+(y)*X]) &&
abs(dpFx[(x)+(y)*X]) >= abs(dpFx[(x - 1) + (y)*X]) && abs(dpFx[(x)+(y)*X]) > abs(dpFx[(x + 1) + (y)*X])) abs(dpFx[(x)+(y)*X]) >= abs(dpFx[(x - 1) + (y)*X]) && abs(dpFx[(x)+(y)*X]) > abs(dpFx[(x + 1) + (y)*X])) {
{
ucpLabel[(x)+(y)*X] = 255;//水平边缘-1 ucpLabel[(x)+(y)*X] = 255;//水平边缘-1
} }
} }
} }
}); });
//标记连通域 //标记连通域,根据不同连通域显示不同颜色
cv::Mat labels; cv::Mat labels;
int ilabel = cv::connectedComponents(label, labels); int ilabel = cv::connectedComponents(label, labels);
//绘制连通域 //绘制连通域
std::vector<cv::Vec3b> labelColor(ilabel); std::vector<cv::Vec3b> labelColor(ilabel);
for (int i = 0; i < ilabel; i++) for (int i = 0; i < ilabel; i++) {
{
labelColor[i] = cv::Vec3b(rand() % 256, rand() % 256, rand() % 256); labelColor[i] = cv::Vec3b(rand() % 256, rand() % 256, rand() % 256);
} }
cv::Mat labelImage; cv::Mat labelImage;
cv::cvtColor(image, labelImage, cv::COLOR_GRAY2BGR); cv::cvtColor(image, labelImage, cv::COLOR_GRAY2BGR);
for (int y = 1; y < Y - 1; y++) {
for (int y = 1; y < Y - 1; y++) for (int x = 1; x < X - 1; x++) {
{
for (int x = 1; x < X - 1; x++)
{
int lb = labels.at<int>(y, x); int lb = labels.at<int>(y, x);
if (lb != 0) if (lb != 0) {
{
labelImage.at<cv::Vec3b>(y, x) = labelColor[lb]; labelImage.at<cv::Vec3b>(y, x) = labelColor[lb];
} }
} }
...@@ -179,16 +73,13 @@ int eyemEdgesPixel(EyemImage tpImage, double dThresh) ...@@ -179,16 +73,13 @@ int eyemEdgesPixel(EyemImage tpImage, double dThresh)
int eyemEdgesSubpixel(EyemImage tpImage, int iFilter, int iLow, int iHigh) int eyemEdgesSubpixel(EyemImage tpImage, int iFilter, int iLow, int iHigh)
{ {
cv::Mat image(tpImage.iHeight, tpImage.iWidth, CV_8UC1, tpImage.vpImage); cv::Mat image = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
if (image.empty()) { if (image.empty()) {
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
} }
int X = image.cols, Y = image.rows; int X = image.cols, Y = image.rows;
uchar *upF = image.data; uchar *upF = image.data;
/*计算偏导*/ /*计算偏导*/
double *dpFx = (double *)malloc(X*Y * sizeof(double)); double *dpFx = (double *)malloc(X*Y * sizeof(double));
double *dpFy = (double *)malloc(X*Y * sizeof(double)); double *dpFy = (double *)malloc(X*Y * sizeof(double));
...@@ -196,10 +87,8 @@ int eyemEdgesSubpixel(EyemImage tpImage, int iFilter, int iLow, int iHigh) ...@@ -196,10 +87,8 @@ int eyemEdgesSubpixel(EyemImage tpImage, int iFilter, int iLow, int iHigh)
double *dpMag = (double *)malloc(X*Y * sizeof(double)); double *dpMag = (double *)malloc(X*Y * sizeof(double));
cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void { cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void {
for (int y = range.start; y < range.end; y++) for (int y = range.start; y < range.end; y++) {
{ for (int x = 1; x < X - 1; x++) {
for (int x = 1; x < X - 1; x++)
{
dpFx[(x)+(y)*X] = 0.5*((double)(upF[(x + 1) + (y)*X]) - (double)(upF[(x - 1) + (y)*X])); dpFx[(x)+(y)*X] = 0.5*((double)(upF[(x + 1) + (y)*X]) - (double)(upF[(x - 1) + (y)*X]));
dpFy[(x)+(y)*X] = 0.5*((double)(upF[(x)+(y + 1)*X]) - (double)(upF[(x)+(y - 1)*X])); dpFy[(x)+(y)*X] = 0.5*((double)(upF[(x)+(y + 1)*X]) - (double)(upF[(x)+(y - 1)*X]));
dpMag[(x)+(y)*X] = sqrt(dpFx[(x)+(y)*X] * dpFx[(x)+(y)*X] + dpFy[(x)+(y)*X] * dpFy[(x)+(y)*X]); dpMag[(x)+(y)*X] = sqrt(dpFx[(x)+(y)*X] * dpFx[(x)+(y)*X] + dpFy[(x)+(y)*X] * dpFy[(x)+(y)*X]);
...@@ -213,81 +102,55 @@ int eyemEdgesSubpixel(EyemImage tpImage, int iFilter, int iLow, int iHigh) ...@@ -213,81 +102,55 @@ int eyemEdgesSubpixel(EyemImage tpImage, int iFilter, int iLow, int iHigh)
cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void { cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void {
for (int y = range.start; y < range.end; y++) for (int y = range.start; y < range.end; y++)
for (int x = 1; x < (X - 1); x++) for (int x = 1; x < (X - 1); x++) {
{ if (dpMag[(x)+(y)*X] > 25) {
if (dpMag[(x)+(y)*X] > 25)
{
//判断边缘 //判断边缘
if (abs(dpFy[(x)+(y)*X]) >= abs(dpFx[(x)+(y)*X]) && if (abs(dpFy[(x)+(y)*X]) >= abs(dpFx[(x)+(y)*X]) &&
abs(dpFy[(x)+(y)*X]) >= abs(dpFy[(x)+(y - 1)*X]) && abs(dpFy[(x)+(y)*X]) > abs(dpFy[(x)+(y + 1)*X])) abs(dpFy[(x)+(y)*X]) >= abs(dpFy[(x)+(y - 1)*X]) && abs(dpFy[(x)+(y)*X]) > abs(dpFy[(x)+(y + 1)*X])) {
{
ucpLabel[(x)+(y)*X] = 255;//垂直边缘-2 ucpLabel[(x)+(y)*X] = 255;//垂直边缘-2
} }
else if (abs(dpFx[(x)+(y)*X]) > abs(dpFy[(x)+(y)*X]) && else if (abs(dpFx[(x)+(y)*X]) > abs(dpFy[(x)+(y)*X]) &&
abs(dpFx[(x)+(y)*X]) >= abs(dpFx[(x - 1) + (y)*X]) && abs(dpFx[(x)+(y)*X]) > abs(dpFx[(x + 1) + (y)*X])) abs(dpFx[(x)+(y)*X]) >= abs(dpFx[(x - 1) + (y)*X]) && abs(dpFx[(x)+(y)*X]) > abs(dpFx[(x + 1) + (y)*X])) {
{
ucpLabel[(x)+(y)*X] = 255;//水平边缘-1 ucpLabel[(x)+(y)*X] = 255;//水平边缘-1
} }
} }
} }
}); });
cv::Mat labels;
cv::connectedComponents(label, labels);
//所有边缘 //所有边缘
EyemOcsDXY temp; EyemOcsDXY edge;
std::vector<EyemOcsDXY> edges; std::vector<EyemOcsDXY> edges;
cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void { cv::parallel_for_(cv::Range(1, Y - 1), [&](const cv::Range& range) -> void {
for (int y = range.start; y < range.end; y++) for (int y = range.start; y < range.end; y++)
for (int x = 1; x < (X - 1); x++) for (int x = 1; x < (X - 1); x++) {
{ if (ucpLabel[(x)+(y)*X] != 0) {
if (ucpLabel[(x)+(y)*X] != 0)
{
//判断边缘 //判断边缘
if (abs(dpFy[(x)+(y)*X]) >= abs(dpFx[(x)+(y)*X]) && if (abs(dpFy[(x)+(y)*X]) >= abs(dpFx[(x)+(y)*X]) &&
abs(dpFy[(x)+(y)*X]) >= abs(dpFy[(x)+(y - 1)*X]) && abs(dpFy[(x)+(y)*X]) > abs(dpFy[(x)+(y + 1)*X])) abs(dpFy[(x)+(y)*X]) >= abs(dpFy[(x)+(y - 1)*X]) && abs(dpFy[(x)+(y)*X]) > abs(dpFy[(x)+(y + 1)*X])) {
{
//垂直边缘 //垂直边缘
double a, b, c, u; double a, b, c, u;
a = dpMag[(x)+(y - 1)*X]; a = dpMag[(x)+(y - 1)*X];
b = dpMag[(x)+(y)*X]; b = dpMag[(x)+(y)*X];
c = dpMag[(x)+(y + 1)*X]; c = dpMag[(x)+(y + 1)*X];
u = 0.5*(a - c) / (a - b - b + c); u = 0.5*(a - c) / (a - b - b + c);
temp.dX = (float)x + 0.5f; edge.dX = (float)x + 0.5f;
temp.dY = (float)y + 0.5f + (float)u; edge.dY = (float)y + 0.5f + (float)u;
edges.push_back(temp); edges.push_back(edge);
} }
else if (abs(dpFx[(x)+(y)*X]) > abs(dpFy[(x)+(y)*X]) && else if (abs(dpFx[(x)+(y)*X]) > abs(dpFy[(x)+(y)*X]) &&
abs(dpFx[(x)+(y)*X]) >= abs(dpFx[(x - 1) + (y)*X]) && abs(dpFx[(x)+(y)*X]) > abs(dpFx[(x + 1) + (y)*X])) abs(dpFx[(x)+(y)*X]) >= abs(dpFx[(x - 1) + (y)*X]) && abs(dpFx[(x)+(y)*X]) > abs(dpFx[(x + 1) + (y)*X])) {
{
//水平边缘 //水平边缘
double a, b, c, u; double a, b, c, u;
a = dpMag[(x - 1) + (y)*X]; a = dpMag[(x - 1) + (y)*X];
b = dpMag[(x)+(y)*X]; b = dpMag[(x)+(y)*X];
c = dpMag[(x + 1) + (y)*X]; c = dpMag[(x + 1) + (y)*X];
u = 0.5*(a - c) / (a - b - b + c); u = 0.5*(a - c) / (a - b - b + c);
temp.dX = (float)x + 0.5f + (float)u; edge.dX = (float)x + 0.5f + (float)u;
temp.dY = (float)y + 0.5f; edge.dY = (float)y + 0.5f;
edges.push_back(temp); edges.push_back(edge);
} }
} }
} }
}); });
//cv::RNG rng;
//cv::Mat show;
//cv::cvtColor(image.clone(), show, cv::COLOR_GRAY2BGR);
//int cnt = 0;
//for (int i = 0; i < contours.size(); i++)
//{
// cv::Vec3b color = cv::Vec3b(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
// for (int j = 0; j < contours[i].size(); j++)
// {
// cnt++;
// show.at<cv::Vec3b>(contours[i][j]) = color;
// }
// //drawContours(show, contours, i, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3);
//}
//释放资源 //释放资源
free((void *)ucpLabel); free((void *)ucpLabel);
free((void *)dpFx); free((void *)dpFx);
...@@ -319,7 +182,6 @@ int eyemSkeleton(EyemImage tpImage, cv::Mat &skeleton) ...@@ -319,7 +182,6 @@ int eyemSkeleton(EyemImage tpImage, cv::Mat &skeleton)
if (image.empty()) { if (image.empty()) {
return FUNC_IMAGE_NOT_EXIST; return FUNC_IMAGE_NOT_EXIST;
} }
thinning(image, skeleton);
return FUNC_OK; return FUNC_OK;
} }
......
...@@ -168,8 +168,7 @@ static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weigh ...@@ -168,8 +168,7 @@ static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weigh
std::memset(sa, 0, sizeof(sa)); std::memset(sa, 0, sizeof(sa));
std::memset(sb, 0, sizeof(sb)); std::memset(sb, 0, sizeof(sb));
std::memset(sx, 0, sizeof(sx)); std::memset(sx, 0, sizeof(sx));
for (int i = 0; i < iPtnNum; i++) for (int i = 0; i < iPtnNum; i++) {
{
sa[0] += weights[i]; sa[0] += weights[i];
sa[1] += weights[i] * taPoints[i].dX; sa[1] += weights[i] * taPoints[i].dX;
sa[3] += weights[i] * taPoints[i].dX*taPoints[i].dX; sa[3] += weights[i] * taPoints[i].dX*taPoints[i].dX;
...@@ -185,7 +184,6 @@ static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weigh ...@@ -185,7 +184,6 @@ static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weigh
//solve ax=b //solve ax=b
bool solved = cv::solve(a, b, x, cv::DECOMP_SVD); bool solved = cv::solve(a, b, x, cv::DECOMP_SVD);
if (!solved) if (!solved)
return; return;
...@@ -247,8 +245,7 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d ...@@ -247,8 +245,7 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d
break; break;
} }
for (int it = 0; it < 50; it++) for (int n = 0; n < 50; n++) {
{
float sum_dist = .0, sum_w = .0; float sum_dist = .0, sum_w = .0;
/*calculate parameter*/ /*calculate parameter*/
...@@ -260,8 +257,7 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d ...@@ -260,8 +257,7 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d
cv::AutoBuffer<float> dist(iPtnNum); cv::AutoBuffer<float> dist(iPtnNum);
/*calculate distance*/ /*calculate distance*/
for (int k = 0; k < iPtnNum; k++) for (int k = 0; k < iPtnNum; k++) {
{
dist[k] = fabs(nx*(float)taPoints[k].dX + ny*(float)taPoints[k].dY - (nx*px + ny*py)) / sqrt(nx*nx + ny*ny); dist[k] = fabs(nx*(float)taPoints[k].dX + ny*(float)taPoints[k].dY - (nx*px + ny*py)) / sqrt(nx*nx + ny*ny);
sum_dist += dist[k]; sum_dist += dist[k];
} }
...@@ -290,10 +286,8 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d ...@@ -290,10 +286,8 @@ int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double d
static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsDABC &tpLine) static void fitLine2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsDABC &tpLine)
{ {
std::vector<cv::Point2f> points; std::vector<cv::Point2f> points;
for (int i = 0; i < iPtnNum; i++) for (int i = 0; i < iPtnNum; i++) {
{ if (taPoints[i].bValid) {
if (taPoints[i].bValid)
{
points.push_back(cv::Point2f((float)taPoints[i].dX, (float)taPoints[i].dY)); points.push_back(cv::Point2f((float)taPoints[i].dX, (float)taPoints[i].dY));
} }
} }
...@@ -316,8 +310,7 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC & ...@@ -316,8 +310,7 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &
} }
auto taPoints = std::vector<EyemOcsDXY2D>(iPtnNum); auto taPoints = std::vector<EyemOcsDXY2D>(iPtnNum);
for (int i = 0; i < iPtnNum; i++) for (int i = 0; i < iPtnNum; i++) {
{
taPoints[i].bValid = true; taPoints[i].bValid = true;
taPoints[i].dX = taPoint[i].dX; taPoints[i].dX = taPoint[i].dX;
taPoints[i].dY = taPoint[i].dY; taPoints[i].dY = taPoint[i].dY;
...@@ -328,29 +321,24 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC & ...@@ -328,29 +321,24 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &
//Initialize the parameters with Robust method //Initialize the parameters with Robust method
fitLine2D_wods(iPtnNum, &taPoints[0], tpLine); fitLine2D_wods(iPtnNum, &taPoints[0], tpLine);
for (int it = 0; it < 50; it++) for (int n = 0; n < 50; n++) {
{
double sr = 0.0, r = 0.0; double sr = 0.0, r = 0.0;
/* calculate distances */ /* calculate distances */
for (int i = 0; i < iPtnNum; i++) for (int i = 0; i < iPtnNum; i++) {
{
taPoints[i].bValid = true; taPoints[i].bValid = true;
taPoints[i].dE = std::pow(calcDist2D(taPoints[i], tpLine.dA, tpLine.dB, tpLine.dC), 2); taPoints[i].dE = std::pow(calcDist2D(taPoints[i], tpLine.dA, tpLine.dB, tpLine.dC), 2);
} }
//sort by dE //sort by dE
std::sort(taPoints.begin(), taPoints.end(), 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; taPoints[i].bValid = false;
} }
/* Run again... */ /* Run again... */
fitLine2D_wods(iPtnNum, &taPoints[0], tpLine); fitLine2D_wods(iPtnNum, &taPoints[0], tpLine);
for (int i = 0; i < iPtnNum; i++) for (int i = 0; i < iPtnNum; i++) {
{ if (taPoints[i].bValid) {
if (taPoints[i].bValid)
{
r = std::pow(calcDist2D(taPoints[i], tpLine.dA, tpLine.dB, tpLine.dC), 2); r = std::pow(calcDist2D(taPoints[i], tpLine.dA, tpLine.dB, tpLine.dC), 2);
sr += r; sr += r;
} }
...@@ -361,7 +349,6 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC & ...@@ -361,7 +349,6 @@ int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &
if (std::abs(err - min_err) < EPS) if (std::abs(err - min_err) < EPS)
break; break;
min_err = err; min_err = err;
} }
return FUNC_OK; return FUNC_OK;
...@@ -372,10 +359,8 @@ static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsD ...@@ -372,10 +359,8 @@ static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsD
return; return;
} }
std::vector<cv::Point2d> points; std::vector<cv::Point2d> points;
for (int i = 0; i < iPtnNum; i++) for (int i = 0; i < iPtnNum; i++) {
{ if (taPoints[i].bValid) {
if (taPoints[i].bValid)
{
points.push_back(cv::Point2d(taPoints[i].dX, taPoints[i].dY)); points.push_back(cv::Point2d(taPoints[i].dX, taPoints[i].dY));
} }
} }
...@@ -386,8 +371,7 @@ static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsD ...@@ -386,8 +371,7 @@ static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY2D *taPoints, EyemOcsD
cv::Mat x = cv::Mat(3, 1, CV_64F); cv::Mat x = cv::Mat(3, 1, CV_64F);
memset(sa, 0, sizeof(sa)); memset(sa, 0, sizeof(sa));
memset(sb, 0, sizeof(sb)); memset(sb, 0, sizeof(sb));
for (size_t i = 0; i < points.size(); i++) for (int i = 0; i < points.size(); i++) {
{
sa[0] += (double)points[i].x; sa[0] += (double)points[i].x;
sa[1] += (double)points[i].y; sa[1] += (double)points[i].y;
sa[2] += 1.0; sa[2] += 1.0;
...@@ -425,25 +409,21 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS ...@@ -425,25 +409,21 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS
double rms = .0; double rms = .0;
fitCircle2D_wods(iPtnNum, &taPoints[0], tpCircle); fitCircle2D_wods(iPtnNum, &taPoints[0], tpCircle);
//迭代计算 //迭代计算
for (int it = 0; it < 50; it++) for (int n = 0; n < 50; n++) {
{
double sr = 0.0, r = 0.0; double sr = 0.0, r = 0.0;
for (int i = 0; i < iPtnNum; i++) for (int i = 0; i < iPtnNum; i++) {
{
taPoints[i].bValid = true; taPoints[i].bValid = true;
taPoints[i].dE = std::pow(calcDist(taPoints[i], tpCircle) - tpCircle.dR, 2); taPoints[i].dE = std::pow(calcDist(taPoints[i], tpCircle) - tpCircle.dR, 2);
} }
//排序 //排序
std::sort(taPoints.begin(), taPoints.end(), 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; taPoints[i].bValid = false;
} }
fitCircle2D_wods(iPtnNum, &taPoints[0], tpCircle); fitCircle2D_wods(iPtnNum, &taPoints[0], tpCircle);
//计算RMS //计算RMS
for (int i = 0; i < iPtnNum; i++) for (int i = 0; i < iPtnNum; i++) {
{
if (taPoints[i].bValid) if (taPoints[i].bValid)
{ {
r = std::pow(calcDist(taPoints[i], tpCircle) - tpCircle.dR, 2); r = std::pow(calcDist(taPoints[i], tpCircle) - tpCircle.dR, 2);
...@@ -459,3 +439,65 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS ...@@ -459,3 +439,65 @@ int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS
return FUNC_OK; return FUNC_OK;
} }
static void fitCircle2D_wods(int iPtnNum, const EyemOcsDXY *taPoints, float *weights, float *circle)
{
//计算系数
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 (int i = 0; i < iPtnNum; i++)
{
sa[0] += (double)weights[i] * taPoints[i].dX;
sa[1] += (double)weights[i] * taPoints[i].dY;
sa[2] += (double)weights[i];
sa[3] += (double)weights[i] * taPoints[i].dX*taPoints[i].dX;
sa[4] += (double)weights[i] * taPoints[i].dX*taPoints[i].dY;
sa[7] += (double)weights[i] * taPoints[i].dY*taPoints[i].dY;
sb[1] += (double)weights[i] * taPoints[i].dX*(-taPoints[i].dX*taPoints[i].dX - taPoints[i].dY*taPoints[i].dY);
sb[2] += (double)weights[i] * taPoints[i].dY*(-taPoints[i].dX*taPoints[i].dX - taPoints[i].dY*taPoints[i].dY);
}
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;
}
int eyemRobustFitCircle(int iPtnNum, EyemOcsDXY *taPoints, int iCalcMode, double dRobustCoef, EyemOcsDXYR &tpCircle)
{
return FUNC_OK;
}
int eyemRobustFitPlane(int iPtnNum, EyemOcsDXYZ *taPoint, int iCalcMode, double dRobustCoef, EyemOcsDABCD &tpPlane)
{
return FUNC_OK;
}
int eyemFitPlane(int iPtnNum, EyemOcsDXYZ *taPoint, int numToIgnore, double &dRMS, EyemOcsDABCD &tpPlane)
{
return FUNC_OK;
}
int eyemFitLineRANSAC(int iPtnNum, EyemOcsDXY *taPoint, EyemOcsDABC &tpLine)
{
return FUNC_OK;
}
int eyemFitCircleRANSAC(int iPtnNum, EyemOcsDXY *taPoint, EyemOcsDXYR &tpCircle)
{
return FUNC_OK;
}
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <opencv.hpp> #include <opencv.hpp>
#ifndef EXPORTS #ifndef EXPORTS
#define EXPORTS __declspec(dllexport) #define EXPORTS __declspec(dllexport)
#endif #endif
...@@ -431,7 +430,7 @@ extern "C" { ...@@ -431,7 +430,7 @@ extern "C" {
// 函数接口 // 函数接口
EXPORTS int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &tpLine); EXPORTS int eyemFitLine(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, EyemOcsDABC &tpLine);
EXPORTS int eyemRobustFitLine(int iPtnNum, EyemOcsDXY *taPoint, int iCalcMode, double dRobustCoef, 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 eyemFitPlane(int, EyemOcsDXYZ[], int, double, EyemOcsDABCD &);
EXPORTS int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS, EyemOcsDXYR &tpCircle); EXPORTS int eyemFitCircle(int iPtnNum, EyemOcsDXY *taPoint, int numToIgnore, double &RMS, EyemOcsDXYR &tpCircle);
EXPORTS int eyemFitEllipse(int, EyemOcsDXY[], int, double, EyemOcsDXYLSQ *); EXPORTS int eyemFitEllipse(int, EyemOcsDXY[], int, double, EyemOcsDXYLSQ *);
EXPORTS int eyemFitEllipseC(int, EyemOcsDXY[], int, double, double[]); EXPORTS int eyemFitEllipseC(int, EyemOcsDXY[], int, double, double[]);
...@@ -659,7 +658,7 @@ extern "C" { ...@@ -659,7 +658,7 @@ extern "C" {
#endif #endif
// 函数接口 // 函数接口
EXPORTS int eyemEdgesPixel(EyemImage tpImage, double dThresh); EXPORTS int eyemEdgesPixel(EyemImage tpImage, double dThreshold);
EXPORTS int eyemEdgesSubpixel(EyemImage tpImage, IntPtr *hObject, EyemOcsDXY **tpEdges, int iFilter, int iLow, int iHigh); EXPORTS int eyemEdgesSubpixel(EyemImage tpImage, IntPtr *hObject, EyemOcsDXY **tpEdges, int iFilter, int iLow, int iHigh);
EXPORTS int eyemSkeleton(EyemImage tpImage, EyemImage &skeleton); EXPORTS int eyemSkeleton(EyemImage tpImage, EyemImage &skeleton);
EXPORTS int eyemSobelAmp(EyemImage tpImage, EyemImage &ImaAmp); EXPORTS int eyemSobelAmp(EyemImage tpImage, EyemImage &ImaAmp);
...@@ -790,6 +789,27 @@ extern "C" { ...@@ -790,6 +789,27 @@ extern "C" {
////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////
// 深度学习目标检测器(eyemNNDetector.cpp)
//
typedef struct {
EyemRect bboxes[100];
} BboxContainer;
#ifdef __cplusplus
extern "C" {
#endif
// 函数接口
EXPORTS int eyemInitNNDetector(const char *detectorConfigPath, const char *detectorModelPath);
EXPORTS int eyemNNDetector(EyemImage tpImage, int *ipNum, BboxContainer &container);
#ifdef __cplusplus
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////
// 其他工具(eyemMisc.cpp) // 其他工具(eyemMisc.cpp)
// //
......
此文件类型无法预览
...@@ -177,8 +177,9 @@ ...@@ -177,8 +177,9 @@
<ClInclude Include="eyemMat.h" /> <ClInclude Include="eyemMat.h" />
<ClInclude Include="eyemMath.h" /> <ClInclude Include="eyemMath.h" />
<ClInclude Include="eyemMisc.h" /> <ClInclude Include="eyemMisc.h" />
<ClInclude Include="eyemNNDetector.h" />
<ClInclude Include="eyemSmooth.h" /> <ClInclude Include="eyemSmooth.h" />
<ClInclude Include="nnDetector.h" /> <ClInclude Include="eyemCodeDetector.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
<ClInclude Include="yoloWrapper.h" /> <ClInclude Include="yoloWrapper.h" />
</ItemGroup> </ItemGroup>
...@@ -199,8 +200,9 @@ ...@@ -199,8 +200,9 @@
<ClCompile Include="eyemMatch.cpp" /> <ClCompile Include="eyemMatch.cpp" />
<ClCompile Include="eyemMath.cpp" /> <ClCompile Include="eyemMath.cpp" />
<ClCompile Include="eyemMisc.cpp" /> <ClCompile Include="eyemMisc.cpp" />
<ClCompile Include="eyemNNDetector.cpp" />
<ClCompile Include="eyemSmooth.cpp" /> <ClCompile Include="eyemSmooth.cpp" />
<ClCompile Include="nnDetector.cpp" /> <ClCompile Include="eyemCodeDetector.cpp" />
<ClCompile Include="libopencv.cpp" /> <ClCompile Include="libopencv.cpp" />
<ClCompile Include="yoloWrapper.cpp" /> <ClCompile Include="yoloWrapper.cpp" />
</ItemGroup> </ItemGroup>
......
...@@ -57,15 +57,18 @@ ...@@ -57,15 +57,18 @@
<ClInclude Include="yoloWrapper.h"> <ClInclude Include="yoloWrapper.h">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="nnDetector.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="barcodeDetector.h"> <ClInclude Include="barcodeDetector.h">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="eyemDataCode.h"> <ClInclude Include="eyemDataCode.h">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="eyemCodeDetector.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="eyemNNDetector.h">
<Filter>源文件</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="eyemLib.cpp"> <ClCompile Include="eyemLib.cpp">
...@@ -119,15 +122,18 @@ ...@@ -119,15 +122,18 @@
<ClCompile Include="libopencv.cpp"> <ClCompile Include="libopencv.cpp">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="nnDetector.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="barcodeDetector.cpp"> <ClCompile Include="barcodeDetector.cpp">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="eyemDataCode.cpp"> <ClCompile Include="eyemDataCode.cpp">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="eyemCodeDetector.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="eyemNNDetector.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="eyemLib.rc"> <ResourceCompile Include="eyemLib.rc">
......
#include "eyemNNDetector.h"
#include "yoloWrapper.h"
class NNDetector::Impl {
public:
Impl() {}
~Impl() {}
//目标检测
std::vector<cv::Rect> detect(const cv::Mat& img);
//目标检测器
std::shared_ptr<YoloWrapper> detector_;
};
NNDetector::NNDetector(const std::string & detector_config_path,
const std::string & detector_model_path)
{
p = cv::makePtr<NNDetector::Impl>();
if (!detector_config_path.empty() && !detector_model_path.empty()) {
p->detector_ = std::make_shared<YoloWrapper>();
p->detector_->init(detector_config_path, detector_model_path);
}
else {
p->detector_ = NULL;
}
}
std::vector<cv::Rect> NNDetector::detect(cv::InputArray img)
{
CV_Assert(!img.empty());
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();
}
return p->detect(input);
}
std::vector<cv::Rect> NNDetector::Impl::detect(const cv::Mat& img) {
return detector_->forward(img);
}
int eyemInitNNDetector(const char *detectorConfigPath, const char *detectorModelPath)
{
try {
pNNDetector = cv::makePtr<NNDetector>(detectorConfigPath, detectorModelPath);
}
catch (const std::exception& e) {
std::cout << e.what() << std::endl;
return FUNC_CANNOT_CALC;
}
std::unique_ptr<NNDetector> dd;
dd.reset(new NNDetector(detectorConfigPath, detectorModelPath));
dd->detect(cv::Mat());
dd.reset();
return FUNC_OK;
}
int eyemNNDetector(EyemImage tpImage, int *ipNum, BboxContainer &container)
{
cv::Mat src = cv::Mat(tpImage.iHeight, tpImage.iWidth, MAKETYPE(tpImage.iDepth, tpImage.iChannels), tpImage.vpImage).clone();
if (src.empty()) {
return FUNC_IMAGE_NOT_EXIST;
}
auto target = pNNDetector->detect(src);
//结果
for (int i = 0; i < target.size() && i < 100; ++i) {
EyemRect bbox; bbox.iXs = target[i].x; bbox.iYs = target[i].y; bbox.iWidth = target[i].width; bbox.iHeight = target[i].height;
container.bboxes[i] = bbox;
}
*ipNum = static_cast<int>(target.size());
return FUNC_OK;
}
#pragma once
//
// eyemNNDetector¡¤±êÍ·
//
#ifndef __EYEMNNDETECTOR_H
#define __EYEMNNDETECTOR_H
#include "eyemLib.h"
class NNDetector {
public:
NNDetector(const std::string& detector_config_path = "",
const std::string& detector_model_path = "");
NNDetector() {};
std::vector<cv::Rect> detect(cv::InputArray img);
protected:
class Impl;
cv::Ptr<Impl> p;
};
cv::Ptr<NNDetector> pNNDetector;
#endif/* __EYEMNNDETECTOR_H */
\ No newline at end of file \ No newline at end of file
#include "yoloWrapper.h" #include "yoloWrapper.h"
int YoloWrapper::init(const cv::String& detector_config_path, int YoloWrapper::init(const std::string& detector_config_path,
const cv::String& detector_model_path) { const std::string& detector_model_path) {
if (!detector_config_path.empty() && !detector_model_path.empty()) { if (!detector_config_path.empty() && !detector_model_path.empty()) {
//加载并初始化网络 //加载并初始化网络
net_ = cv::dnn::readNet(detector_config_path, detector_model_path); net_ = cv::dnn::readNet(detector_config_path, detector_model_path);
...@@ -62,11 +62,9 @@ std::vector<cv::Rect> YoloWrapper::forward(cv::Mat img) { ...@@ -62,11 +62,9 @@ std::vector<cv::Rect> YoloWrapper::forward(cv::Mat img) {
} }
} }
} }
std::vector<int> indices; std::vector<int> indices;
//非极大值抑制 //非极大值抑制
cv::dnn::NMSBoxes(bboxes, confidences, 0.01f, 0.05f, indices); cv::dnn::NMSBoxes(bboxes, confidences, 0.01f, 0.05f, indices);
//裁剪区域 //裁剪区域
auto points = std::vector<cv::Rect>(); auto points = std::vector<cv::Rect>();
for (int i = 0; i < indices.size(); i++) { for (int i = 0; i < indices.size(); i++) {
......
...@@ -13,7 +13,6 @@ class YoloWrapper ...@@ -13,7 +13,6 @@ class YoloWrapper
{ {
public: public:
YoloWrapper() {}; YoloWrapper() {};
~YoloWrapper() {};
int init(const std::string& config_path, const std::string& model_path); int init(const std::string& config_path, const std::string& model_path);
std::vector<cv::Rect> forward(cv::Mat img); std::vector<cv::Rect> forward(cv::Mat img);
private: private:
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!