code_device/hgdriver/ImageProcess/CISTestImageProcess.cpp

304 lines
7.7 KiB
C++
Raw Permalink Normal View History

2022-12-28 01:56:54 +00:00
#include "CISTestImageProcess.h"
int CISTestImageProcess::test(const cv::Mat& image, CISTestResult& result)
{
2023-01-06 07:03:37 +00:00
#if 0
2022-12-30 09:54:27 +00:00
//std::vector<cv::RotatedRect> marks;
//int res = findMarks(image, marks);
//return res;
2022-12-31 03:06:46 +00:00
result.scaleXY1 = -1;
result.scaleXY2 = -1;
result.scaleXY3 = -1;
2022-12-30 09:54:27 +00:00
if (image.channels() != 3)
2023-01-06 07:03:37 +00:00
return -1; //ͼƬ<CDBC><C6AC><EFBFBD>Dz<EFBFBD>ɫͼ
int res = 0;
2022-12-30 09:54:27 +00:00
cv::Mat hsv;
cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV_FULL);
std::vector<cv::Mat> hsv_channels;
cv::split(hsv, hsv_channels);
cv::Mat mask_s, range_h, range_temp;
2023-01-06 07:03:37 +00:00
cv::inRange(hsv_channels[1], 110, 255, mask_s); //<2F><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>[50, 220]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2022-12-30 09:54:27 +00:00
//cv::imwrite("range1.jpg", mask_s);
cv::inRange(hsv_channels[0], 0, 84, range_h); //<2F><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>[220, 255]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cv::inRange(hsv_channels[0], 213, 255, range_temp); //<2F><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>[220, 255]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
range_h &= mask_s;
range_h |= range_temp & mask_s;
2022-12-31 03:06:46 +00:00
//cv::imwrite("range3.jpg", range_h);
2023-01-06 07:03:37 +00:00
res = findEllipse(range_h, result.scaleXY1);
if (res != 0)
return -2;
cv::inRange(hsv_channels[0], 30, 140, range_h); //<2F><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>[220, 255]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2022-12-30 09:54:27 +00:00
range_h &= mask_s;
2022-12-31 03:06:46 +00:00
//cv::imwrite("range4.jpg", range_h);
2023-01-06 07:03:37 +00:00
res = findEllipse(range_h, result.scaleXY2);
if (res != 0)
return -2;
2022-12-30 09:54:27 +00:00
cv::inRange(hsv_channels[0], 128, 213, range_h); //<2F><><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>[220, 255]<5D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
range_h &= mask_s;
2022-12-31 03:06:46 +00:00
//cv::imwrite("range5.jpg", range_h);
2023-01-06 07:03:37 +00:00
res = findEllipse(range_h, result.scaleXY3);
if (res != 0)
return -2;
#else
cv::Mat thre;
if (image.channels() == 3)
cv::cvtColor(image, thre, cv::COLOR_BGR2GRAY);
else
thre = image.clone();
cv::threshold(thre, thre, 127, 255, cv::THRESH_BINARY);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
findContours(thre, contours, hierarchy, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);
std::vector<cv::Point> contour;
for (size_t i = 0; i < contours.size(); i++)
{
if (hierarchy[i][3] == -1)
continue;
cv::Rect rect = cv::boundingRect(contours[i]);
if (rect.width < 100)
continue;
else
{
contour = contours[i];
break;
}
}
if (contour.size() < 3)
return -2;
2022-12-30 09:54:27 +00:00
2023-01-06 07:03:37 +00:00
cv::RotatedRect box = cv::fitEllipse(contour);
if (box.angle < -45)
{
box.angle += 90;
float temp = box.size.width;
box.size.width = box.size.height;
box.size.height = temp;
}
2023-03-01 03:04:07 +00:00
if (box.angle < -45)
{
box.angle += 90;
float temp = box.size.width;
box.size.width = box.size.height;
box.size.height = temp;
}
if (box.angle > 45)
{
box.angle -= 90;
float temp = box.size.width;
box.size.width = box.size.height;
box.size.height = temp;
}
2023-01-06 07:03:37 +00:00
if (box.angle > 45)
{
box.angle -= 90;
float temp = box.size.width;
box.size.width = box.size.height;
box.size.height = temp;
}
2023-01-09 08:03:12 +00:00
result.w = box.size.width;
result.h = box.size.height;
result.scaleXY = box.size.width / box.size.height;
2023-01-06 07:03:37 +00:00
#endif
2022-12-28 01:56:54 +00:00
return 0;
}
CISTestImageProcess::CISTestImageProcess()
{
}
void CISTestImageProcess::findContours(const cv::Mat& src, std::vector<std::vector<cv::Point>>& contours,
std::vector<cv::Vec4i>& hierarchy, int retr, int method, cv::Point offset)
{
#if CV_VERSION_REVISION <= 6
CvMat c_image = src;
#else
CvMat c_image;
c_image = cvMat(src.rows, src.cols, src.type(), src.data);
c_image.step = src.step[0];
c_image.type = (c_image.type & ~cv::Mat::CONTINUOUS_FLAG) | (src.flags & cv::Mat::CONTINUOUS_FLAG);
#endif
cv::MemStorage storage(cvCreateMemStorage());
CvSeq* _ccontours = nullptr;
#if CV_VERSION_REVISION <= 6
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint(offset));
#else
cvFindContours(&c_image, storage, &_ccontours, sizeof(CvContour), retr, method, CvPoint{ offset.x, offset.y });
#endif
if (!_ccontours)
{
contours.clear();
return;
}
cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage));
size_t total = all_contours.size();
contours.resize(total);
cv::SeqIterator<CvSeq*> it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
reinterpret_cast<CvContour*>(c)->color = static_cast<int>(i);
int count = c->total;
int* data = new int[static_cast<size_t>(count * 2)];
cvCvtSeqToArray(c, data);
for (int j = 0; j < count; j++)
{
contours[i].push_back(cv::Point(data[j * 2], data[j * 2 + 1]));
}
delete[] data;
}
hierarchy.resize(total);
it = all_contours.begin();
for (size_t i = 0; i < total; i++, ++it)
{
CvSeq* c = *it;
int h_next = c->h_next ? reinterpret_cast<CvContour*>(c->h_next)->color : -1;
int h_prev = c->h_prev ? reinterpret_cast<CvContour*>(c->h_prev)->color : -1;
int v_next = c->v_next ? reinterpret_cast<CvContour*>(c->v_next)->color : -1;
int v_prev = c->v_prev ? reinterpret_cast<CvContour*>(c->v_prev)->color : -1;
hierarchy[i] = cv::Vec4i(h_next, h_prev, v_next, v_prev);
}
storage.release();
}
2022-12-30 09:54:27 +00:00
void CISTestImageProcess::convexHull(const std::vector<cv::Point>& src, std::vector<cv::Point>& dst, bool clockwise)
{
CvMemStorage* storage = cvCreateMemStorage(); //
CvSeq* ptseq = cvCreateSeq(CV_SEQ_KIND_GENERIC | CV_32SC2, sizeof(CvContour), sizeof(CvPoint), storage); //ptseqstorage
//<2F><>src<72>ĵ㼯<C4B5><E3BCAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ptseq
for (const cv::Point& item : src)
{
CvPoint p;
p.x = item.x;
p.y = item.y;
cvSeqPush(ptseq, &p);
}
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CvSeq* hull = cvConvexHull2(ptseq, nullptr, clockwise ? CV_CLOCKWISE : CV_COUNTER_CLOCKWISE, 0);
if (hull == nullptr)
{
//<2F>ͷ<EFBFBD>storage
cvReleaseMemStorage(&storage);
return;
}
//<2F><><EFBFBD><EFBFBD>dst
dst.clear();
for (int i = 0, hullCount = hull->total; i < hullCount; i++)
dst.push_back(**CV_GET_SEQ_ELEM(CvPoint*, hull, i));
//<2F>ͷ<EFBFBD>storage
cvReleaseMemStorage(&storage);
}
2022-12-28 01:56:54 +00:00
int CISTestImageProcess::findPaperContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy, cv::RotatedRect& paperRect)
{
std::vector<cv::Point> maxContour;
if (contours.size() < 1) return {};
for (size_t i = 0, length = hierarchy.size(); i < length; i++)
if (hierarchy[i][3] == -1)
for (const auto& item : contours[i])
maxContour.push_back(item);
if (maxContour.size() == 0)
return -1;
paperRect = cv::minAreaRect(maxContour);
if (paperRect.angle < -45)
{
paperRect.angle += 90;
float temp = paperRect.size.width;
paperRect.size.width = paperRect.size.height;
paperRect.size.height = temp;
}
if (paperRect.angle > 45)
{
paperRect.angle -= 90;
float temp = paperRect.size.width;
paperRect.size.width = paperRect.size.height;
paperRect.size.height = temp;
}
return 0;
}
int CISTestImageProcess::classfiyContours(const std::vector<std::vector<cv::Point>>& contours, std::vector<std::vector<cv::Point>>& marks,
std::vector<std::vector<cv::Point>>& colorBlocks,
std::vector<std::vector<cv::Point>>& grayBlocks)
{
marks.clear();
colorBlocks.clear();
grayBlocks.clear();
for (size_t i = 0; i < contours.size(); i++)
{
double area = cv::contourArea(contours[i]);
}
return 0;
}
2022-12-30 09:54:27 +00:00
int CISTestImageProcess::findEllipse(const cv::Mat& image, double& scale_xy, double areaThre)
2022-12-28 01:56:54 +00:00
{
2022-12-30 09:54:27 +00:00
//cv::imwrite("range2.jpg", image);
2022-12-28 01:56:54 +00:00
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
2022-12-30 09:54:27 +00:00
findContours(image, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
std::vector<cv::Point> maxContour;
for (std::vector<std::vector<cv::Point>>::iterator iter = contours.begin(); iter != contours.end(); iter++)
if (cv::contourArea(*iter) > areaThre)
for (const auto& item : *iter)
maxContour.push_back(item);
convexHull(maxContour, maxContour);
2022-12-28 01:56:54 +00:00
2023-01-06 07:03:37 +00:00
if (maxContour.size() < 3)
return -1;
2022-12-30 09:54:27 +00:00
cv::RotatedRect box = cv::fitEllipse(maxContour);
2022-12-28 01:56:54 +00:00
2022-12-30 09:54:27 +00:00
if (box.angle < -45)
{
box.angle += 90;
float temp = box.size.width;
box.size.width = box.size.height;
box.size.height = temp;
}
if (box.angle > 45)
{
box.angle -= 90;
float temp = box.size.width;
box.size.width = box.size.height;
box.size.height = temp;
}
2022-12-31 03:06:46 +00:00
scale_xy = box.size.width / box.size.height;
2022-12-30 09:54:27 +00:00
return 0;
2022-12-28 01:56:54 +00:00
}