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