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);
}
}
}