Commit 37ea7eac 张士柳

1 个父辈 c13fd1b2
......@@ -1233,7 +1233,6 @@ namespace eyemLib_Sharp
Console.WriteLine("读图失败!");
return;
}
Stopwatch sw = new Stopwatch();
sw.Restart();
string file = fileName.Split(new string[] { "\\" }, StringSplitOptions.RemoveEmptyEntries)[2];
......@@ -1301,7 +1300,7 @@ namespace eyemLib_Sharp
//tpHsvModel.dpRangeL = new double[] { 100, 43, 46 }; tpHsvModel.dpRangeU = new double[] { 124, 255, 255 };
//tpHsvModel.dpRangeLExt = new double[] { 0, 0, 0 }; tpHsvModel.dpRangeUExt = new double[] { 0, 0, 0 };
//eyemClassifier(image);
flag = eyemLibImpl(image, out tpDstImg);
//flag = eyemLibImpl(image, out tpDstImg);
//float[] fFeatures = new float[512];
//eyemExtractWithONNX(image, fFeatures);
//string ftrs = string.Join(" ", fFeatures).Trim();
......@@ -1322,9 +1321,9 @@ namespace eyemLib_Sharp
// bitmap.Save("D:\\ResOut\\" + file);
//}
//eyemImageFree(ref tpMatchImg);
eyemImageFree(ref tpDstImg);
eyemImageFree(ref image);
return;
//eyemImageFree(ref tpDstImg);
//eyemImageFree(ref image);
//return;
//EyemImage templ, search;
//flag = eyemImageRead("D://批量测试图像//template.png", -1, out templ);
......@@ -1630,7 +1629,7 @@ namespace eyemLib_Sharp
bitmap.Save(System.Windows.Forms.Application.StartupPath + "\\ResOut\\" + file);
}
//< 解码测试
////< 解码测试
//int ipNum; EyemBarCode* tpResults;
//DataCodeHandle hObject;
//int iRes = eyemDetectAndDecode(image, tpRoi, file.Replace(".png", ""), "QR_CODE|DATA_MATRIX", out hObject, out tpResults, out ipNum, false, 11, 5, 128, 256);
......
......@@ -62,6 +62,7 @@ std::vector<std::string> CodeDetector::detectAndDecode(cv::InputArray img, std::
}
logger.t("__eyemDetectAndDecodeUseNN__detectAndDecode__:图像格式转换完成");
_mtx.lock();
int x = 0;
//识别
logger.t("__eyemDetectAndDecodeUseNN__detectAndDecode__:开始识别二维码");
std::vector<cv::Rect> bboxes = p->detect(input);
......
......@@ -935,7 +935,6 @@ extern "C" {
EXPORTS int eyemDrawCircle(EyemImage tpImage, EyemOcsDXYR tpCircle);
EXPORTS int eyemDrawRectangle(EyemImage tpImag, EyemRect tpRect);
EXPORTS int eyemTrainImageSampler(EyemImage tpImage, int iSize, const char *ccClassName, const char *ccToPath, EyemImage *tpMatchImg, EyemImage *tpDstImg);
EXPORTS int eyemBuildTrainFile(const char *filePath, const char *fileName, bool shuffle = true);
#ifdef __cplusplus
}
......
此文件类型无法预览
......@@ -4462,71 +4462,130 @@ int eyemCountObjectIrregularParts(EyemImage tpImage, EyemRect tpRoi, const char
}
else
{
//先用自动算法点,如果不行判断为散料
int trayNum[4];
int iRet = eyemCountObjectE(tpImage, tpRoi, "", trayNum, tpDstImg);
if (iRet == FUNC_OK) {
//输出结果
for (int i = 0; i < 4; i++) {
//输出结果
ipReelNum[i] = trayNum[i];
break;
}
return FUNC_OK;
}
else {
//判断为散料
cv::threshold(srcPrev, binary, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
cv::morphologyEx(binary, binary, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(25, 25)));
//计算直方图
int hist[256];
for (int y = 0; y < 256; y++) hist[y] = 0;
for (int y = 0; y < Y; y++)
cv::threshold(srcPrev, binary, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
//假设有部分颜色较深料带影响
cv::morphologyEx(binary, binary, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(5, 5)));
//计算直方图
int hist[256];
for (int y = 0; y < 256; y++) hist[y] = 0;
for (int y = 0; y < Y; y++)
{
uchar *uPtr = srcPrev.data + y * X;
for (int x = 0; x < srcPrev.cols; x++, uPtr++)
{
uchar *uPtr = srcPrev.data + y * X;
for (int x = 0; x < srcPrev.cols; x++, uPtr++)
if ((binary.data)[(x)+(y)*X] == 255)
{
if ((binary.data)[(x)+(y)*X] == 255)
{
hist[*uPtr]++;
}
hist[*uPtr]++;
}
}
cv::threshold(srcPrev, binary, Otsu(hist) + 5, 255, cv::THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours, contourFilter;
//连接在一起(散料用)
cv::Mat binaryEx;
cv::morphologyEx(binary, binaryEx, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(75, 75)));
}
cv::threshold(srcPrev, binary, Otsu(hist), 255, cv::THRESH_BINARY);
//判断这些连通域相似性(从面积、平均灰度、最大灰度等判断)再确定阈值与面积过滤参数
cv::Mat labels, stats, centroids;
int nccomps = cv::connectedComponentsWithStats(binary, labels, stats, centroids);
//统计每个连通域的信息
struct TE
{
double Area, Mean;
TE() {}
TE(double Area, double Mean) :Area(Area), Mean(Mean) {}
};
std::vector<TE> Tes;
for (int i = 1; i < nccomps; i++)
{
auto meanRect = cv::Rect(stats.ptr<int>(i)[cv::CC_STAT_LEFT], stats.ptr<int>(i)[cv::CC_STAT_TOP],
stats.ptr<int>(i)[cv::CC_STAT_WIDTH], stats.ptr<int>(i)[cv::CC_STAT_HEIGHT]);
//掩膜
cv::Mat mask(Y, X, CV_8UC1, cv::Scalar(0));
cv::findContours(binaryEx, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
for (int i = 0; i < contours.size(); i++)
cv::Mat mask = (labels(meanRect) == i);
Tes.push_back(TE(stats.ptr<int>(i)[cv::CC_STAT_AREA], cv::mean(srcPrev(meanRect), mask)[0]));
}
//确定相似度(每一点计算距离其他点的欧氏距离)
struct tMap
{
TE te;
double match;
tMap() {}
tMap(TE te, double match) :te(te), match(match) {}
bool operator >(const tMap &te)const
{
return match > te.match;
}
bool operator <(const tMap &te)const
{
return match < te.match;
}
};
std::vector<tMap> tMaps;
for (int i = 0; i < (int)Tes.size(); i++)
{
double sumMatch = 0.0;
for (int j = 0; j < (int)Tes.size(); j++)
{
sumMatch += std::sqrt(std::pow(Tes[i].Area - Tes[j].Area, 2) + std::pow(Tes[i].Mean - Tes[j].Mean, 2));
}
tMaps.push_back(tMap(Tes[i], sumMatch));
}
//排序
std::sort(tMaps.begin(), tMaps.end(), std::less<tMap>());
//确定单个元件尺寸与灰度值
double sinPartsArea = tMaps[0].te.Area; double sinPartsMean = tMaps[0].te.Mean;
//根据灰度值重新进行二值化
cv::threshold(srcPrev, binary, sinPartsMean*0.75, 255, cv::THRESH_BINARY);
//重新计算连通域
nccomps = cv::connectedComponentsWithStats(binary, labels, stats, centroids);
//对连通域过滤
std::vector<uchar> colors(nccomps + 1, 0);
for (int i = 1; i < nccomps; i++)
{
colors[i] = 255;
if (stats.ptr<int>(i)[cv::CC_STAT_AREA] <= 2) {
colors[i] = 0;
}
}
//过滤
cv::parallel_for_(cv::Range(0, Y), [&](const cv::Range& range)->void {
for (int y = range.start; y < range.end; y++)
{
double contourArea = cv::contourArea(contours[i]);
if (contourArea > 15000)
uint8_t *ptrRow = binary.ptr<uint8_t>(y);
for (int x = 0; x < X; x++)
{
//绘制掩膜
cv::drawContours(mask, contours, i, cv::Scalar(255), -1);
int label = labels.ptr<int>(y)[x];
CV_Assert(0 <= label && label <= nccomps);
ptrRow[x] = colors[label];
}
}
//粗略计数
cv::Mat labels, stats, centroids;
int numObj = cv::connectedComponentsWithStats(binary&mask, labels, stats, centroids);
//坐标图
binary = cv::Scalar(0);
//画图
double *dpCent = (double *)centroids.data;
for (int j = 1; j < numObj; j++)
});
//确定范围
std::vector<std::vector<cv::Point>> contours, contourFilter;
//连接在一起(散料用)
cv::Mat binaryEx;
cv::morphologyEx(binary, binaryEx, cv::MORPH_DILATE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(95, 95)));
//掩膜,用于排除零星干扰
cv::Mat mask(Y, X, CV_8UC1, cv::Scalar(0));
cv::findContours(binaryEx, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
for (int i = 0; i < contours.size(); i++)
{
double contourArea = cv::contourArea(contours[i]);
if (contourArea > 15000)
{
//面积过滤
if (stats.ptr<int>(j)[cv::CC_STAT_AREA] > 2) {
cv::circle(cc, cv::Point(cvRound((float)dpCent[(0) + (j)* 2]), cvRound((float)dpCent[(1) + (j)* 2])), 1, cv::Scalar(0, 255, 0, 255));
binary.at<uchar>(cv::Point(cvRound((float)dpCent[(0) + (j)* 2]), cvRound((float)dpCent[(1) + (j)* 2]))) = 255;
}
cv::Moments mu = cv::moments(contours[i]);
cv::Point2f reelCenter(float(mu.m10 / mu.m00), float(mu.m01 / mu.m00));
cv::drawMarker(cc, reelCenter, cv::Scalar(0, 0, 238, 255), 1, 35, 2);
//绘制掩膜
cv::drawContours(mask, contours, i, cv::Scalar(255), -1);
}
}
//粗略计数
int numObj = cv::connectedComponentsWithStats(binary&mask, labels, stats, centroids);
//坐标图
binary = cv::Scalar(0);
//画图
for (int j = 1; j < numObj; j++)
{
cv::Point centroid(cvRound(centroids.ptr<double>(j)[0]), cvRound(centroids.ptr<double>(j)[1]));
cv::circle(cc, centroid, 1, cv::Scalar(0, 255, 0, 255));
binary.at<uchar>(centroid) = 255;
}
}
//计数
std::vector<cv::Point> idx;
......@@ -4801,7 +4860,7 @@ int eyemCountObjectE(EyemImage tpImage, EyemRect tpRoi, const char *fileName, in
//判断适用哪种算法
if (!useTrackMethod)
{
const int filterSize = 12;
const int filterSize = 17;//因为移远改成17,原12
//去掉料盘深色部分干扰
const int winSize = sinPartSize > 15 ? 5 : 3;//对于部分器件过小的窗口会漏料
cv::Mat srcPrevEx;
......@@ -6968,15 +7027,12 @@ int eyemCountObjectIrregularPartsE(EyemImage tpImage, EyemRect tpRoi, const char
int eyemAchvMatchMat(EyemImage tpImage, EyemRect tpRoi, EyemImage *tpDstImg)
{
CV_Assert(NULL != tpImage.vpImage);
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) {
cv::cvtColor(image, image, cv::COLOR_BGRA2BGR);
}
//转单通道
if (image.channels() != 1)
cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
......@@ -7088,47 +7144,33 @@ int eyemAchvMatchMat(EyemImage tpImage, EyemRect tpRoi, EyemImage *tpDstImg)
//画标记
cv::putText(cc, "OK", cv::Point(170, 270), cv::FONT_HERSHEY_COMPLEX, 8, cv::Scalar(0, 100, 0, 255), 8);
//偏移两侧取更多样本
cv::Point Offset[3] = { cv::Point(-90,0),cv::Point(0,0),cv::Point(90,0) };
cv::Point Offset[1] = { cv::Point(0,0) };
//返回中间一根线的中点位置图像
std::vector<cv::Mat> mats; cv::Mat templateMat;
cv::Mat templateMat;
for (auto&ofset : Offset)
{
cv::Point nstart = start + ofset; cv::Point nend = end + ofset;
//cv::line(cc, nstart, nend, cv::Scalar(0, 255, 0, 255));
cv::Mat linesample(image2.rows, image2.cols, CV_8UC1, cv::Scalar(0));
cv::line(linesample, nstart, nend, cv::Scalar(255), 1);
//去除中心料盘干扰
cv::circle(binary, start, 85, cv::Scalar(0), -1);
cv::Mat sampleLine;
cv::bitwise_and(linesample, binary, sampleLine);
std::vector<cv::Point> idx;
cv::findNonZero(sampleLine, idx);
//
if (idx.empty())
{
//未发现料盘
if (idx.empty()) {
return FUNC_CANNOT_CALC;
}
//保存中间图作为匹配
if (ofset.x == 0 && ofset.y == 0)
{
cv::Point mid = idx[idx.size() / 2];
templateMat = src8U(cv::Rect(cv::Point(mid.x - 64, mid.y - 64), cv::Point(mid.x + 64, mid.y + 64))&cv::Rect(0, 0, X, Y)).clone();
cv::cvtColor(templateMat, templateMat, cv::COLOR_GRAY2RGB);
}
int step = (idx.size() / 27);
if (step < 1) {
step = 1;
}
for (int i = 0; i < idx.size() - 1; i += step)
{
auto p = idx[i];
cv::Mat mat = src8U(cv::Rect(cv::Point(p.x - 64, p.y - 64), cv::Point(p.x + 64, p.y + 64))&cv::Rect(0, 0, X, Y)).clone();
if (mat.cols == mat.rows)
{
mats.push_back(mat);
}
}
cv::Point mid = idx[idx.size() / 2];
templateMat = src8U(cv::Rect(cv::Point(mid.x - 64, mid.y - 64), cv::Point(mid.x + 64, mid.y + 64))&cv::Rect(0, 0, X, Y)).clone();
cv::cvtColor(templateMat, templateMat, cv::COLOR_GRAY2RGB);
break;
}
//<输出匹配图像
tpDstImg->iWidth = templateMat.cols; tpDstImg->iHeight = templateMat.rows; tpDstImg->iDepth = templateMat.depth(); tpDstImg->iChannels = templateMat.channels();
......@@ -7301,7 +7343,6 @@ int eyemInitModel(const char *ccTplName, IntPtr *hModelID)
for (std::vector<std::string>::iterator it = fileNames.begin(); it != fileNames.end(); ++it)
{
std::string fileName = (*it);
cv::Mat tplMat; double matchDeg;
try
{
......@@ -7312,37 +7353,26 @@ int eyemInitModel(const char *ccTplName, IntPtr *hModelID)
logger.t(logModule + "从本地加载模板文件异常...");
return FUNC_CANNOT_CALC;
}
if (!tplMat.empty()) {
cv::Mat _tplMat;
cv::bitwise_not(tplMat, _tplMat);
//载入模板
EyemModelID modelID;
int _Size = tplMat.cols*tplMat.rows * sizeof(unsigned char);
//数据
logger.t(logModule + "分配模板图像内存...");
modelID.vpImage = (unsigned char *)malloc(_Size);
if (NULL == modelID.vpImage)
return FUNC_NOT_ENOUGH_MEM;
//拷贝数据
logger.t(logModule + "拷贝模板数据...");
memcpy(modelID.vpImage, _tplMat.data, _Size);
//位置
modelID.iXs = modelID.iYs = 0;
//宽、高
modelID.iWidth = tplMat.cols; modelID.iHeight = tplMat.rows;
//匹配分数
modelID.dMatchDeg = matchDeg;
//名称?会导致内存泄露吗
logger.t(logModule + "分配模板文件名内存...");
modelID.lpszName = (char *)CoTaskMemAlloc(128);
......@@ -7353,7 +7383,6 @@ int eyemInitModel(const char *ccTplName, IntPtr *hModelID)
strcpy(modelID.lpszName, file);
}
else return FUNC_NOT_ENOUGH_MEM;
//压入容器末尾
logger.t(logModule + "将模板压入容器...");
tpModelID->push_back(modelID);
......@@ -7361,7 +7390,6 @@ int eyemInitModel(const char *ccTplName, IntPtr *hModelID)
}
//输出
*hModelID = reinterpret_cast<IntPtr>(tpModelID);
return FUNC_OK;
}
......@@ -8280,30 +8308,6 @@ int eyemTrainImageSampler(EyemImage tpImage, int iSize, const char *ccClassName,
return FUNC_OK;
}
int eyemBuildTrainFile(const char *filePath, const char *fileName, bool shuffle)
{
std::vector<std::string> fileNames;
cv::glob(filePath, fileNames);
//打乱顺序
std::random_shuffle(fileNames.begin(), fileNames.end());
//写入文件
std::ofstream sw(fileName, std::ios::trunc);
for (auto&item : fileNames) {
std::vector<std::string> items;
split(item, "\\", items);
//
std::vector<std::string> items2(2);
split(items[items.size() - 1], ".", items2);
if (strcmp(items2[3].c_str(), "png") == 0)
{
std::string line = "data/val_images/" + items[items.size() - 1] + "\n";
sw.write(line.c_str(), line.length());
sw.flush();
}
}
sw.close();
return FUNC_OK;
}
#include "eyemStopwatch.h"
int eyemLibImpl(EyemImage tpImage, EyemImage *tpDstImg)
......@@ -8312,32 +8316,33 @@ 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;
//图像尺寸
int X = image.cols, Y = image.rows;
//用于去除黑色坏点干扰
cv::Mat medBlur;
cv::medianBlur(image, medBlur, 3);
//去除局部量斑影响(默认亮斑尺寸不会大于15个像素)
cv::morphologyEx(medBlur, medBlur, cv::MORPH_ERODE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15)));
//图像增强
double min, max;
cv::minMaxLoc(medBlur, &min, &max, NULL);
image.convertTo(image, CV_64FC1);
image -= min;
image /= (max - min);
image *= 65535;
image.convertTo(image, CV_16UC1);
////图像尺寸
//int X = image.cols, Y = image.rows;
////用于去除黑色坏点干扰
//cv::Mat medBlur;
//cv::medianBlur(image, medBlur, 3);
////去除局部量斑影响(默认亮斑尺寸不会大于15个像素)
//cv::morphologyEx(medBlur, medBlur, cv::MORPH_ERODE, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(15, 15)));
////图像增强
//double min, max;
//cv::minMaxLoc(medBlur, &min, &max, NULL);
//image.convertTo(image, CV_64FC1);
//image -= min;
//image /= (max - min);
//image *= 65535;
//image.convertTo(image, CV_16UC1);
cv::Mat image8U;
image.convertTo(image8U, CV_8UC1, 1 / 255.);
//cv::Mat image8U;
//image.convertTo(image8U, CV_8UC1, 1 / 255.);
cv::cvtColor(image8U, image8U, cv::COLOR_BGR2GRAY);
//cv::cvtColor(image8U, image8U, cv::COLOR_BGR2GRAY);
cv::Mat eqhist;
cv::equalizeHist(image8U, eqhist);
//cv::Mat eqhist;
//cv::equalizeHist(image8U, eqhist);
cv::imwrite("0.png",image8U);
//cv::imwrite("0.png",image8U);
return FUNC_OK;
#pragma region
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!