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

    
}

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值