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

    
}

}

相关文章
|
5月前
|
计算机视觉 Python
OpenCV轮廓拟合与凸包的讲解与实战应用(附Python源码)
OpenCV轮廓拟合与凸包的讲解与实战应用(附Python源码)
58 0
|
7月前
|
计算机视觉
OpenCV-计算轮廓周长cv::arcLength
OpenCV-计算轮廓周长cv::arcLength
|
7天前
|
存储 计算机视觉 索引
【OpenCV】-查找并绘制轮廓
【OpenCV】-查找并绘制轮廓
|
5月前
|
算法 计算机视觉 开发者
OpenCV图形检测中绘制图像的轮廓讲解与实战应用(附Python源码)
OpenCV图形检测中绘制图像的轮廓讲解与实战应用(附Python源码)
71 0
|
2月前
|
计算机视觉
OpenCV(三十四):轮廓外接最大、最小矩形和多边形拟合
OpenCV(三十四):轮廓外接最大、最小矩形和多边形拟合
94 0
|
2月前
|
计算机视觉
OpenCV(三十三):计算轮廓面积与轮廓长度
OpenCV(三十三):计算轮廓面积与轮廓长度
60 0
|
2月前
|
计算机视觉 索引
OpenCV(三十二):轮廓检测
OpenCV(三十二):轮廓检测
20 0
|
7月前
|
计算机视觉
OpenCV-计算轮廓面积cv::contourArea
OpenCV-计算轮廓面积cv::contourArea
101 0
|
9月前
|
存储 算法 计算机视觉
【OpenCV图像处理8】图像轮廓
【OpenCV图像处理8】图像轮廓
206 0
|
5月前
|
计算机视觉
[QT5&OpenCV] 边缘检测、轮廓提取及轮廓跟踪
[QT5&OpenCV] 边缘检测、轮廓提取及轮廓跟踪
104 0