tx-gxx-linux/device/gxx-linux/imgproc/CSizedetect.cpp

288 lines
8.7 KiB
C++
Raw Normal View History

2023-04-08 00:56:20 +00:00
#include "CSizedetect.h"
#include <opencv2/opencv.hpp>
#include <opencv2/core/core_c.h>
#include <opencv2/imgproc/imgproc_c.h>
#include "ImageProcess_Public.h"
#include "commondef.h"
void threshold_Mat(const cv::Mat& src, cv::Mat& dst, double thre)
{
if (src.channels() == 3)
{
#ifdef USE_ONENCL
if (cl_res.context)
transforColor_threshold_opencl(src, dst, static_cast<uchar>(thre));
else
#endif
{
cv::Mat gray = hg::transforColor(src);
cv::threshold(gray, dst, thre, 255, cv::THRESH_BINARY);
gray.release();
}
}
else
cv::threshold(src, dst, thre, 255, cv::THRESH_BINARY);
}
void 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();
}
std::vector<cv::Point> getMaxContour(const std::vector<std::vector<cv::Point>>& contours, const std::vector<cv::Vec4i>& hierarchy)
{
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);
return maxContour;
}
cv::RotatedRect getBoundingRect(const std::vector<cv::Point>& contour)
{
if (contour.empty()) return {};
cv::RotatedRect rect = minAreaRect(contour);
if (rect.angle < -45)
{
rect.angle += 90;
float temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
}
if (rect.angle > 45)
{
rect.angle -= 90;
float temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
}
return rect;
}
CSizedetect::CSizedetect(int papaertype) : m_papertype(papaertype),
m_horThre(70),
m_verThre(100)
{
}
CSizedetect::~CSizedetect(void) {}
void CSizedetect::SetPapertype(int papertype) {
m_papertype=papertype;
}
static int x=0;
int CSizedetect::preprocess(cv::Mat &mat, void *unused)
{
if(!mat.empty())
{
float width, height;
cv::Mat thre;
hg::threshold_Mat(mat, thre, 40);
cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(8, 1));
cv::morphologyEx(thre, thre, cv::MORPH_OPEN, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT, cv::Scalar::all(0));
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
hg::findContours(thre, contours, hierarchy, cv::RETR_EXTERNAL);
std::vector<cv::Point> maxContour = hg::getMaxContour(contours, hierarchy);
cv::RotatedRect rect = hg::getBoundingRect(maxContour);
width = rect.size.width;
height = rect.size.height;
printf("\n width =%f ,height = %f ",width,height);
//fastMeasureSize(mat.data,mat.cols,mat.rows,mat.channels(),width,height,40,20,5);
HGSize dstSize;
if(m_supportPaper.count((PaperSize)m_papertype)>0)//包含设置的幅面
{
dstSize=m_supportPaper[(PaperSize)m_papertype];
if((width>(dstSize.width+m_horThre))||(width<(dstSize.width-m_horThre))||(height > (dstSize.height+m_verThre))||(height < (dstSize.height-m_verThre)))
{
return 1;
}
}
}
return 0;
}
void CSizedetect::rotate(float &x, float &y, float angle)
{
float a = x * cos(angle) - y * sin(angle);
float b = x * sin(angle) + y * cos(angle);
x = a;
y = b;
}
void CSizedetect::minAeaRect(const float *x, const float *y, int size, float &width, float &height)
{
float area = width * height;
// rotate 0~90 degree
for (int i = 0; i < 91; ++i)
{
float tmpx = x[0], tmpy = y[0];
rotate(tmpx, tmpy, i);
float xl = tmpx, xr = tmpx, yt = tmpy, yb = tmpy;
// traverse all points
for (int j = 1; j < size; ++j)
{
tmpx = x[j];
tmpy = y[j];
rotate(tmpx, tmpy, i);
if (tmpx < xl)
xl = tmpx;
if (tmpx > xr)
xr = tmpx;
if (tmpy < yb)
yb = tmpy;
if (tmpy > yt)
yt = tmpy;
}
float xx = xr - xl, yy = yt - yb;
if (area > xx * yy)
{
area = xx * yy;
height = xx;
width = yy;
}
}
//
if (height < width)
{
float tmp = height;
height = width;
width = tmp;
}
}
void CSizedetect::fastMeasureSize(const unsigned char *data, int src_width, int src_height, int channels, float &dst_width, float &dst_height, int threshold, int indent, int step)
{
int bytesPerLine = src_width * channels;
int indent_x = indent * channels;
int indent_y = indent;
int step_x = step * channels;
int step_y = step;
int total_count = (bytesPerLine + src_height) * 2 / indent;
if (total_count < 1)
return;
float *points_x = new float[total_count];
float *points_y = new float[total_count];
int points_count = 0;
//top
int rows = src_height / 2;
for (int x = 0; x < bytesPerLine; x += indent_x)
for (int y = 0; y < rows; y += step_y)
if (data[y * bytesPerLine + x] > threshold)
{
points_x[points_count] = x / channels;
points_y[points_count] = y;
points_count++;
break;
}
//bottom
for (int x = 0; x < bytesPerLine; x += indent_x)
for (int y = src_height - 1; y >= rows; y -= step_y)
if (data[y * bytesPerLine + x] > threshold)
{
points_x[points_count] = x / channels;
points_y[points_count] = y;
points_count++;
break;
}
//left
int cols = bytesPerLine / 2;
for (int y = 0; y < src_height; y += indent)
for (int x = 0; x < cols; x += step_x)
if (data[y * bytesPerLine + x] > threshold)
{
points_x[points_count] = x / channels;
points_y[points_count] = y;
points_count++;
break;
}
//right
for (int y = 0; y < src_height; y += indent)
for (int x = bytesPerLine - 1; x >= cols; x -= step_x)
if (data[y * bytesPerLine + x] > threshold)
{
points_x[points_count] = x / channels;
points_y[points_count] = y;
points_count++;
break;
}
if (points_count > 3)
{
dst_width = src_width;
dst_height = src_height;
minAeaRect(points_x, points_y, points_count, dst_width, dst_height);
}
delete[] points_x;
delete[] points_y;
}