code_device/hgdriver/ImageProcess/LineContinuityDetection.cpp

142 lines
3.7 KiB
C++
Raw Permalink Normal View History

2023-10-08 10:03:11 +00:00
#include "LineContinuityDetection.h"
LineContinuityDetection::LineContinuityDetection()
{
}
bool LineContinuityDetection::isContinuous(const cv::Mat& image, double area_threshold)
{
cv::Mat thre;
if (image.channels() != 1)
{
cv::cvtColor(image, thre, cv::COLOR_BGR2GRAY);
cv::threshold(thre, thre, 127, 255, cv::THRESH_OTSU);
}
else
cv::threshold(image, thre, 127, 255, cv::THRESH_OTSU);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
myFindContours(thre, contours, hierarchy, cv::RETR_TREE);
return findBlock(contours, hierarchy, area_threshold);
}
void LineContinuityDetection::myFindContours(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();
}
bool LineContinuityDetection::findBlock(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy, double area_threshold)
{
if (contours.empty())
return false;
std::vector<cv::RotatedRect> rects;
for (size_t i = 0; i < contours.size(); i++)
{
cv::RotatedRect rect = minAreaRect(contours[i]);
rects.push_back(rect);
}
std::vector<int> max_index;
std::vector<float> max_area;
for (size_t i = 0; i < 5; i++)
{
max_index.push_back(0);
max_area.push_back(0);
}
for (size_t i = 0; i < rects.size(); i++)
{
float area = rects[i].size.area();
for (size_t j = 0; j < 5; j++)
{
if (area > max_area[j])
{
max_index.insert(max_index.begin() + j, i);
max_area.insert(max_area.begin() + j, area);
max_index.erase(max_index.begin() + 5);
max_area.erase(max_area.begin() + 5);
break;
}
}
}
for (size_t i = 1; i < 5; i++)
{
int child_count = 0;
int index_temp = hierarchy[max_index[i]][2];
if (index_temp < 0)
return false;
child_count++;
while (hierarchy[index_temp][0] != -1)
{
if (rects[index_temp].size.area() > area_threshold)
child_count++;
index_temp = hierarchy[index_temp][0];
}
if (child_count != 4)
return false;
}
return true;
}