C++ 在不同背景的图像中检测文档的角点
我正在构建一个文档扫描仪应用程序,需要检测图像中文档的角以便裁剪。 到目前为止,我的代码只在图像背景较暗时工作。 但我想为所有背景的人工作 这是我的密码C++ 在不同背景的图像中检测文档的角点,c++,opencv,opencv4android,C++,Opencv,Opencv4android,我正在构建一个文档扫描仪应用程序,需要检测图像中文档的角以便裁剪。 到目前为止,我的代码只在图像背景较暗时工作。 但我想为所有背景的人工作 这是我的密码 vector<Point> getPoints(Mat image) { int width = image.size().width; int height = image.size().height; Mat image_proc = image.clone();
vector<Point> getPoints(Mat image)
{
int width = image.size().width;
int height = image.size().height;
Mat image_proc = image.clone();
vector<vector<Point> > squares;
// blur will enhance edge detection
Mat blurred(image_proc);
cvtColor(image_proc, image_proc, CV_BGR2GRAY);
medianBlur(image_proc, blurred, 9);
Mat gray0(blurred.size(), CV_8U), gray;
vector<vector<Point> > contours;
// find squares in every color plane of the image
for (int c = 0; c < 3; c++)
{
int ch[] = {c, 0};
mixChannels(&blurred, 1, &gray0, 1, ch, 1);
// try several threshold levels
const int threshold_level = 2;
for (int l = 0; l < threshold_level; l++)
{
// Use Canny instead of zero threshold level!
// Canny helps to catch squares with gradient shading
if (l == 0)
{
Canny(gray0, gray, 10, 20, 3); //
// Dilate helps to remove potential holes between edge segments
dilate(gray, gray, Mat(), Point(-1,-1));
}
else
{
gray = gray0 >= (l+1) * 255 / threshold_level;
}
// Find contours and store them in a list
findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
// Test contours
vector<Point> approx;
for (size_t i = 0; i < contours.size(); i++)
{
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if (approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 1000 &&
isContourConvex(Mat(approx)))
{
double maxCosine = 0;
for (int j = 2; j < 5; j++)
{
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
if (maxCosine < 0.3)
squares.push_back(approx);
}
}
}
double largest_area = -1;
int largest_contour_index = 0;
for(int i=0;i<squares.size();i++)
{
double a =contourArea(squares[i],false);
if(a>largest_area)
{
largest_area = a;
largest_contour_index = i;
}
}
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Scaning size() %d",squares.size());
vector<Point> points;
if(squares.size() > 0)
{
points = squares[largest_contour_index];
}
else
{
points.push_back(Point(0, 0));
points.push_back(Point(width, 0));
points.push_back(Point(0, height));
points.push_back(Point(width, height));
}
return points;
}
矢量获取点(Mat图像)
{
int width=image.size().width;
int height=image.size().height;
Mat image_proc=image.clone();
矢量平方;
//模糊将增强边缘检测
Mat模糊(图像处理);
CVT颜色(图像处理、图像处理、CV处理、灰度);
medianBlur(图像处理,模糊,9);
Mat灰色0(模糊的大小(),CV_8U),灰色;
矢量等值线;
//在图像的每个颜色平面中查找正方形
对于(int c=0;c<3;c++)
{
int ch[]={c,0};
混音通道(&模糊,1,&灰色,0,1,通道,1);
//尝试几个阈值级别
const int threshold_level=2;
对于(int l=0;l=(l+1)*255/阈值\u级;
}
//找到等高线并将其存储在列表中
findContours(灰色、等高线、等高线列表、等高线链近似简单);
//测试轮廓
向量近似;
对于(size_t i=0;i1000&&
isContourConvex(材料(近似)))
{
双最大余弦=0;
对于(int j=2;j<5;j++)
{
双余弦=fabs(角度(约[j%4],约[j-2],约[j-1]);
最大余弦=最大值(最大余弦,余弦);
}
如果(最大余弦<0.3)
正方形。推回(大约);
}
}
}
双最大面积=-1;
int最大轮廓指数=0;
对于(int i=0;i最大面积)
{
最大面积=a;
最大等高线指数=i;
}
}
__android_log_print(android_log_VERBOSE,APPNAME,“扫描大小()%d”,squares.size());
矢量点;
如果(squares.size()>0)
{
点=平方[最大轮廓指数];
}
其他的
{
点。向后推(点(0,0));
点。向后推(点(宽度,0));
点。向后推(点(0,高度));
点。向后推(点(宽度、高度));
}
返回点;
}
上述函数返回图像中文档的角点