opencv提取保存轮廓图
pragma once include "open2_public.h" class ld_yjt_sub_image{public: //获取src_mat的轮廓个数,介于nMinSzie和nMaxSize之间的才会放入到evc_contours中 bool getContours(const Mat& src_mat, vector<vector<Point>>& evc_contours, const int& nMinSzie = 500, const int& nMaxSize = 100000); //生成影像名称 string getNewImage(); //提取出子影像文件 bool extract_sub_image(const string& src_image, vector<string>& vec_sub_image); private: //错误信息 CString m_strErrMsg; public: ld_yjt_sub_image(); virtual ~ld_yjt_sub_image(); }; include "stdafx.h" include "ld_yjt_sub_image.h" int g_lImageCount = 0; ld_yjt_sub_image::ld_yjt_sub_image(){} ld_yjt_sub_image::~ld_yjt_sub_image(){} //获取src_mat的轮廓个数,介于nMinSzie和nMaxSize之间的才会放入到evc_contours中bool ld_yjt_sub_image::getContours(const Mat& src_mat, vector>& evc_contours, const int& nMinSzie, const int& nMaxSize) { if (src_mat.empty()) { m_strErrMsg = "原始矩阵为空,无法获取轮廓个数"; return false; } if (src_mat.channels() != 3) { m_strErrMsg.Format("原始矩阵通道个数不为3个"); return false; } Mat mat_clone = src_mat.clone(); //灰度图像 cvtColor(mat_clone, mat_clone, COLOR_BGR2GRAY); //对图像进行二值化 threshold(mat_clone, mat_clone, 80, 255, THRESH_BINARY); vector<vector<Point>> evc_temp_contours; //提取轮廓元素 findContours(mat_clone, evc_temp_contours, CV_RETR_TREE, CHAIN_APPROX_NONE); for (int i = 0; i < evc_temp_contours.size(); i++) { if (evc_temp_contours[i].size() < nMinSzie || evc_temp_contours[i].size() > nMaxSize) //轮廓尺寸过小或者过大 continue; //添加进入容器 evc_contours.push_back(evc_temp_contours[i]); } return true; } //生成影像名称string ld_yjt_sub_image::getNewImage(){ string str_new_image = "new_image"; str_new_image.append(to_string(g_lImageCount++)); str_new_image.append(".jpg"); return str_new_image; } //提取出子影像文件bool ld_yjt_sub_image::extract_sub_image(const string& src_image, vector& vec_sub_image){ Mat src_mat = imread(src_image); if (src_mat.empty()) { m_strErrMsg.Format("打开影像文件[%s]失败", src_image.c_str()); return false; } vector<vector<Point>> evc_contours; if (!getContours(src_mat, evc_contours)) return false; for (int i = 0; i < evc_contours.size(); i++) { //获取区域坐标 Rect rt = boundingRect(evc_contours[i]); //获取倾斜角度 RotatedRect rotate = minAreaRect(evc_contours[i]); //如果角度超过5度,就需要做旋转 float angle = rotate.angle; if (abs(angle) > 5) { cout << "倾斜角度大于5度" << endl; //获取矩形的四个坐标点 Point2f rectpoint[4]; rotate.points(rectpoint); //计算两条边的长度 int line1 = sqrt((rectpoint[1].y - rectpoint[0].y)*(rectpoint[1].y - rectpoint[0].y) + (rectpoint[1].x - rectpoint[0].x)*(rectpoint[1].x - rectpoint[0].x)); int line2 = sqrt((rectpoint[3].y - rectpoint[0].y)*(rectpoint[3].y - rectpoint[0].y) + (rectpoint[3].x - rectpoint[0].x)*(rectpoint[3].x - rectpoint[0].x)); //为了让正方形横着放,所以旋转角度是不一样的 if (line1 > line2) // angle = 90 + angle; //直接克隆一个矩阵 Mat warp_mat = src_mat(rt).clone(); //计算绕图像中点顺时针旋转50度缩放因子为0.8的旋转矩阵 Point center = Point(warp_mat.cols / 2, warp_mat.rows / 2); double scale = 1; //通过上面的旋转细节信息求得旋转矩阵 Mat rot_mat = getRotationMatrix2D(center, angle, scale); //旋转已扭曲图像 warpAffine(warp_mat, warp_mat, rot_mat, warp_mat.size()); //imshow("warp_mat", warp_mat); //再次提取轮廓 vector<vector<Point>> evc_warp_contours; if (!getContours(warp_mat, evc_warp_contours)) return false; for (int j = 0; j<evc_warp_contours.size(); j++) { //获取区域坐标 Rect warp_rt = boundingRect(evc_warp_contours[j]); string ImageName = getNewImage(); imwrite(ImageName, warp_mat(warp_rt)); vec_sub_image.push_back(ImageName); } waitKey(0); } else { cout << "倾斜角度小于5度" << endl; /// 设置目标图像的大小和类型与源图像一致 Mat warp_dst = Mat::zeros(src_mat.rows, src_mat.cols, src_mat.type()); warp_dst.setTo(cv::Scalar(100, 0, 0)); src_mat(rt).copyTo(warp_dst); string str_new_image = getNewImage(); imwrite(str_new_image, warp_dst); vec_sub_image.push_back(str_new_image); } } }