栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++上opencv的常用数组操作

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++上opencv的常用数组操作

1、图像读取与Mat初始化

-1 表示原始格式(对于彩色图像就是BGR), 0 表示灰度图,1表示BGR图像

除了读取图像的方式外还可以通过Mat::zeros,  Mat::ones,   Mat::eye等函数初始化Mat

string path= "image.jpg";
cv::Mat m= imread(path, -1);
cv::Mat m2=Mat::zeros(m.rows, m.cols, CV_8UC1);
2、类型转换

只会改变Mat的数据类型,并不会改变mat的值。imread加载的mat均为CV_8UC3格式,8表示8位(此外还有16位,32位,64位),U表示无符号整数(此外还有短整型S,浮点数F),C3表示3个通道(此外还有一通道C1,二通道C2,四通道C4,n通道C(n))

可以通过mat.type()来获取类型信息

m.convertTo(m, CV_32FC3);
int dtype = m.type();//dtype==CV_32FC3
3、色彩空间转换

共有HSV,LAB,XYZ、Luv等等色彩空间可以转换。

色彩空间转换后请注意查看目标mat的值域与理论值域是否相对应,如果不对应则转换原mat的数据类型,如CV_32FC3【该类型下的BRG图像的最大值应该为1】、CV_8UC1【该类型下的BRG图像的最大值应该为255】

cv::Mat hsv;
cv::cvtColor(m/255, hsv, cv::COLOR_BGR2HSV);
4、数学运算

cv::Mat间可以进行加减乘除运算,其运算方式与正常变量无二异

在运算时最好将mat类型转换为64位float,这样子可以避免运算结果溢出带来不必要的麻烦。如:在CV_8UC1的类型下1-255=254(减法只是表示数值的距离)

cv::Mat mat9 = cv::Mat::ones(9, 9, CV_16FC1)*9;
cv::Mat mat2 = cv::Mat::ones(9, 9, CV_16FC1)*2;
cv::Mat result_18 = mat2.mul(mat9);//逐像素值相乘,得到的还是一个矩阵
cv::Mat resutl_7=mat9-mat2;
cv::Mat resutl_11=mat9+mat2;
cv::Mat resutl_4_5=mat9/mat2;
5、Mat通道的分离与合并

多通道Mat分离为vector数组,vector数组可以合并为多通道Mat

//分割lab三通道mat为包含三个单通道的vector
vector mv;
cv::split(lab, mv);
mv[0] = (mv[0] -50)/2;//把LAB色彩空间的坐标原点移到球模型中间

//将vector内的多个mat合并为一个多通道mat
cv::merge(mv, lab);
6、遍历与取值赋值

其中取值赋值需要区分是单通道mat还是多通道mat,其次要注意mat的元素类型是浮点数还是整形。赋值时只需要交换变量的位置即可 mat.at(i,j)=12;

cv::Mat mat = cv::Mat::ones(9, 9, CV_8UC1)*9; //单通道  uchar
cv::Mat mat3 = cv::Mat::ones(9, 9, CV_16FC3)*9;//多通道  float
for (i = 0;i < mat.rows;i++) {
    for (j = 0;j < mat.cols;j++) {
        int kk= mat.at(i,j);//单通道  uchar
        flaot f1=dis.at(i, j)[0];//3通道  float
        flaot f2=dis.at(i, j)[1];//3通道  float
        flaot f3=dis.at(i, j)[2];//3通道  float
     }
}
7、值域的截取

opencv下值域的截取需要通过threshold函数实现,通过threshold函数可以将大于阈值的部分置0,也可以将小于阈值的部分置0

如下列代码,通过组合操作,即提取出了im中[0.05,0.3]的值域部分的mask,将目标值域外的数值置0

//将大于0.3的部分置1
Mat mat_maxout_mask = cut_value(im, .3, 0);
//将小于0.05的部分置1
Mat mat_minout_mask = cut_value(im, .05, 1);
//值域外的mask
Mat all_out_mask=mat_maxout_mask +mat_minout_mask 
//值域内的mask
Mat all_mask=1-all_out_mask;
//目标数据   0*n=0 1*n=1
Mat dst_data=all_mask*im;

//int type:0 获取大于阈值的部分,1 获取小于阈值的部分
//该函数只适用于值域为0,1的float形mat,因为测试中发现threshold函数只支持CV_8UC1,所以针对性的缩放了值域。
//对于不同值域的mat需要自行调整参数
cv::Mat cut_value(cv::Mat im,float thres_,int type) {
    cv::Mat result,tmp;
    thres_ = thres_ * 255;
    tmp = im * 255;
    tmp.convertTo(tmp, CV_8UC1);
    if (type == 0) {
        cv::threshold(tmp, result, thres_, 255,THRESH_BINARY);//大于阈值返回 最大值 255 小于返回0
    }
    else {
        cv::threshold(tmp, result, thres_, 255, THRESH_BINARY_INV);//小于阈值返回 最大值 255  小于返回0
    }
    result.convertTo(result, CV_32FC1);
    result = result / 255;
    return result;
}
#将im中小于minv的部分和大于maxv的部分置0
cv::Mat get_dst(cv::Mat im,float minv=0.05, float maxv=0.3):
    //将大于0.3的部分置1
    cv::Mat mat_maxout_mask = cut_value(im, maxv, 0);
    //将小于0.05的部分置1
    cv::Mat mat_minout_mask = cut_value(im, minv, 1);
    //值域外的mask
    cv::Mat all_out_mask=mat_maxout_mask +mat_minout_mask; 
    //值域内的mask
    cv::Mat all_mask=1-all_out_mask;
    //目标数据   0*n=0 1*n=1
    cv::Mat dst_data=all_mask*im;
    return dst_data;
8、最大值、最小值、均值、求和等统计值的计算

其中最大值和最小值是针对所有通道。而sum、mean函数的作用域是按单通道计算,所以针对多个通道有多个结果

double minv = 0.0, maxv = 0.0;
double* minp = &minv;
double* maxp = &maxv;
cv::minMaxIdx(mat, minp, maxp);
//假设mat为三通道
printf_s("channel 1  sum:%f  mean:%f ,channel 2  sum:%f  mean:%f ,channel 3  sum:%f  mean:%f ,min:%f  max:%fn", sum(mat)[0], mean(mat)[0],sum(mat)[1], mean(mat)[1],sum(mat)[2], mean(mat)[2], minv, maxv);

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/604589.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号