#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> contours; std::vector hierarchy; myFindContours(thre, contours, hierarchy, cv::RETR_TREE); return findBlock(contours, hierarchy, area_threshold); } void LineContinuityDetection::myFindContours(const cv::Mat& src, std::vector>& contours, std::vector& 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 all_contours(cvTreeToNodeSeq(_ccontours, sizeof(CvSeq), storage)); size_t total = all_contours.size(); contours.resize(total); cv::SeqIterator it = all_contours.begin(); for (size_t i = 0; i < total; i++, ++it) { CvSeq* c = *it; reinterpret_cast(c)->color = static_cast(i); int count = c->total; int* data = new int[static_cast(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(c->h_next)->color : -1; int h_prev = c->h_prev ? reinterpret_cast(c->h_prev)->color : -1; int v_next = c->v_next ? reinterpret_cast(c->v_next)->color : -1; int v_prev = c->v_prev ? reinterpret_cast(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>& contours, const std::vector& hierarchy, double area_threshold) { if (contours.empty()) return false; std::vector rects; for (size_t i = 0; i < contours.size(); i++) { cv::RotatedRect rect = minAreaRect(contours[i]); rects.push_back(rect); } std::vector max_index; std::vector 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; }