opencv c++对表格进行提取,校正,并且按顺序裁剪出其中的单元格

#include<opencv2/opencv.hpp>
#include<iostream>
#include<algorithm>

using namespace cv;
using namespace std;

bool sortrectx(Rect& rect1, Rect& rect2);
bool sortrecty(Rect& rect1, Rect& rect2);
Point2f* sortpoint(Point2f* arr, int lenth);
void getList(Mat img);

int main()
{
	Mat src = imread("E:\\dataset\\dataset\\202\\chart.png");

	if (src.empty())
	{
		cout << "fail to load the picture" << endl;
		return -1;

	}
	Mat dst;
	resize(src, dst, Size(0, 0), 0.3, 0.4, INTER_AREA);

	Mat srclone = dst.clone();
	//namedWindow("dst", WINDOW_NORMAL);
	//imshow("dst", dst);



	//namedWindow("表格图", WINDOW_AUTOSIZE);
	//imshow("表格图", src);

	Mat gray;
	cvtColor(srclone, gray, COLOR_BGR2GRAY);
	//namedWindow("灰度图", WINDOW_AUTOSIZE);
	//imshow("灰度图",gray);

	Mat yuzhi;
	adaptiveThreshold(~gray, yuzhi, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);

	//namedWindow("阈值图", WINDOW_AUTOSIZE);
	//imshow("阈值图", yuzhi);

	Mat structure = getStructuringElement(MORPH_RECT, Size(2, 2));
	//erode(yuzhi, yuzhi, structure, Point(-1, -1));
	//dilate(yuzhi, yuzhi, structure, Point(-1, -1));


	//imshow("dilate", yuzhi);

	vector<Vec4i>hierarchy;
	vector<vector<Point>>contours;

	findContours(yuzhi, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());

	//cout << contours.size();

	vector<vector<Point>>contours_poly(contours.size());

	int indexmax = 0;
	double areamax = 0;

	for (int i = 0; i < contours.size(); i++)
	{
		double area = contourArea(contours[i]);

		if (area < 20)
			continue;

		//drawContours(srclone, contours, i, Scalar(0, 255, 0),1,8);


		approxPolyDP(contours[i], contours_poly[i], 10, true);//输出是多边形的顶点


		if (area > areamax)
		{
			areamax = area;
			indexmax = i;
		}



	}
	for (size_t j = 0; j < contours_poly[indexmax].size(); j++)
	{
		cout << contours_poly[indexmax][j] << endl;

	}

	drawContours(srclone, contours, indexmax, Scalar(0, 255, 0), 1, 8);

	//namedWindow("lunkuo", WINDOW_NORMAL);
	//imshow("lunkuo", srclone);

	//Rect bondrect;
	//bondrect = boundingRect(Mat(contours_poly[indexmax]));

	//Mat roi = dst(bondrect).clone();
	//namedWindow("roi", WINDOW_NORMAL);
	//imshow("roi", roi);

	Mat polypic = Mat(dst.size(), CV_8UC3, Scalar(0, 0, 0));
	drawContours(polypic, contours, indexmax, Scalar(0, 255, 0), 1, 8);
	//namedWindow("polypic", WINDOW_NORMAL);
	//imshow("polypic", polypic);


	Mat outpic = Mat(Size(1800, 1200), dst.type(), Scalar(255, 255, 255));

	Point2f dstpoint[4];
	dstpoint[0] = Point2f(100, 100);
	dstpoint[1] = Point2f(100, 1100);
	dstpoint[2] = Point2f(1700, 100);
	dstpoint[3] = Point2f(1700, 1100);


	Point2f arr[4] = { contours_poly[indexmax][0],contours_poly[indexmax][1] ,contours_poly[indexmax][2] ,contours_poly[indexmax][3] };

	Point2f* srcpoint = sortpoint(arr, 3);

	for (size_t j = 0; j < 4; j++)
	{
		cout << srcpoint[j] << endl;

	}




	Mat transmat = getPerspectiveTransform(srcpoint, dstpoint);
	warpPerspective(dst, outpic, transmat, outpic.size(), INTER_LANCZOS4, 0, Scalar(255, 255, 255));


	//namedWindow("outpic", WINDOW_AUTOSIZE);
	//imshow("outpic", outpic);

	//imwrite("E:\\图片\\outpic.jpg", outpic);

	getList(outpic);



	waitKey();

	return 0;


}

Point2f* sortpoint(Point2f* arr, int lenth)
{
	Point2f t;

	for (int i = 0; i < lenth; i++)
		for (int j = 0; j < lenth - 1 - i; j++)
		{
			if (arr[j].x > arr[j + 1].x)
			{
				t = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = t;
			}



		}

	if (arr[0].y > arr[1].y)
	{
		t = arr[0];
		arr[0] = arr[1];
		arr[1] = t;
	}

	if (arr[2].y > arr[3].y)
	{
		t = arr[2];
		arr[2] = arr[3];
		arr[3] = t;
	}


	return arr;

}

void getList(Mat img)
{
	Mat gray;
	cvtColor(img, gray, COLOR_BGR2GRAY);

	Mat yuzhi;
	adaptiveThreshold(~gray, yuzhi, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);


	//namedWindow("阈值图", WINDOW_AUTOSIZE);
	//imshow("阈值图", yuzhi);
	Mat horizontal = yuzhi.clone();
	Mat vertical = yuzhi.clone();

	int scale = 20;
	int horizontalsize = horizontal.cols / scale;
	int verticalsize = vertical.rows / scale;

	Mat horizontalstructure = getStructuringElement(MORPH_RECT, Size(horizontalsize, 1));
	erode(horizontal, horizontal, horizontalstructure, Point(-1, -1));
	dilate(horizontal, horizontal, horizontalstructure, Point(-1, -1));
	dilate(horizontal, horizontal, horizontalstructure, Point(-1, -1));

	//namedWindow("横线", WINDOW_AUTOSIZE);
	//imshow("横线", horizontal);

	Mat verticalstructure = getStructuringElement(MORPH_RECT, Size(1, verticalsize));
	erode(vertical, vertical, verticalstructure, Point(-1, -1));
	dilate(vertical, vertical, verticalstructure, Point(-1, -1));

	//namedWindow("竖线", WINDOW_AUTOSIZE);
	//imshow("竖线", vertical);

	Mat joint;
	bitwise_and(horizontal, vertical, joint);

	//namedWindow("交点", WINDOW_AUTOSIZE);
	//imshow("交点", joint);

	Mat mask = horizontal + vertical;
	//namedWindow("结果", WINDOW_AUTOSIZE);
	//imshow("结果", mask);

	vector<Vec4i>hierarchy;
	vector<vector<Point>>contours;


	findContours(mask, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
	//cout << contours.size() << endl;


	vector<vector<Point>>contours_poly(contours.size());
	vector<Rect>boundRect;
	vector<Mat>Rois;
	vector<Rect>rects;


	for (int i = 0; i < contours.size(); i++)
	{
		double area = contourArea(contours[i]);
		if (area < 10000 || area>300000)
			continue;
		approxPolyDP(contours[i], contours_poly[i], 3, true);

		boundRect.push_back(boundingRect(Mat(contours_poly[i])));
	
	}

	sort(boundRect.begin(), boundRect.end(), sortrecty);


	
	//sort(boundRect.begin(), boundRect.end(), sortrecty);

	vector<Rect> ::iterator iter = boundRect.begin();
	for (int i = 0; i < boundRect.size()-6; i++)
	{
		if (i % 7 == 0)
		{
			sort(iter+i, iter+7+i, sortrectx);//注意如果表格不是我这样的,这块代码适当修改即可

	    }

	}

	

	for (int i = 0; i < boundRect.size(); i++)
	{
		Rois.push_back(img(boundRect[i]).clone());
	}

	//cout << boundRect.size() << endl;
	cout << Rois.size();

	vector<Mat>image(Rois.size());

	for (int i = 0; i < Rois.size(); i++)
	{
		cvtColor(Rois[i], Rois[i], COLOR_BGR2GRAY);
		char name[30];
		sprintf_s(name, "rois%d", i);
		//namedWindow(name, WINDOW_AUTOSIZE);
		//imshow(name, Rois[i]);
		string Img_Name = "E:\\dataset\\dataset\\203\\" + to_string(10+i)+  "." + to_string(257)+" .jpg";
		imwrite(Img_Name, Rois[i]);

	}

}

bool sortrectx(Rect& rect1, Rect& rect2)
{
	return rect1.tl().x <= rect2.tl().x;

 }

bool sortrecty(Rect& rect1, Rect& rect2)
{
	return rect1.tl().y <= rect2.tl().y;

}

//代码不懂得地方,或者有误的欢迎大家讨论

效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
就展示这几张图,后面的就不做展示了

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

z_alien

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值