142 lines
3.7 KiB
C++
142 lines
3.7 KiB
C++
|
#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;
|
||
|
}
|