天天看點

opencv提取儲存輪廓圖pragma onceinclude "open2_public.h"include "stdafx.h"include "ld_yjt_sub_image.h"

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

    
}           

繼續閱讀