opencv的Mat相关操作

news/2024/11/8 23:05:11/
  1. cv Mat类型的使用
    下载安装好opencv,使用时只需添加如下头文件:
#include<opencv2/opencv.hpp>

另外在工程的属性页中要添加opencv的包含目录与库目录:
在这里插入图片描述
在这里插入图片描述
在写稍大一些工程的时候,尽量不要直接用using namespace cv; 因为在实践的过程中,发现会出现一些报错,例如错误“ACCESS_MASK”不明确,就是因为opencv的using namespace cv和windows.h中ACCESS_MASK定义冲突,解决的办法就是把using namespace cv注掉, 在使用的时候加上cv::,当然也有其他的方法可以解决,也就是去处理windows.h头文件,具体可以看博客:
https://blog.csdn.net/jacke121/article/details/110121394?spm=1001.2014.3001.5506
2. cv Mat类型的声明
利用矩阵尺寸和类型参数构造Mat:

cv::Mat Matname( int  rows, int  cols, int type);
cv::Mat pred_uvd_jts_29(29, 3, CV_32FC1);//声明一个29行3列数据类型为32位float单通道的矩阵

其中,float: 4字节,6-7位有效数字 -3.4E-38 到 3.4E38
double: 8字节,15~16位有效数字 -1.7E-308 到 1.7E308
Float 32bits:CvMat数据结构参数:CV_32FC1,CV_32FC2,CV_32FC3,CV_32FC4
Double 64bits:CvMat数据结构参数:CV_64FC1,CV_64FC2,CV_64FC3,CV_64FC4,
要注意,cv Mat类型是有double类型的,参数为CV_64F,注意使用时,深度学习模型的推理结果类型为torch.float32,所以声明的Mat也要为CV_32F,否则类型不对应会导致结果不正确,相差离谱。

声明全0矩阵(cv::Mat::zeros):

cv::Mat pred_xyz_jts_29 = cv::Mat::zeros(29, 3, CV_32FC1);

声明全1矩阵:

cv::Mat mm = cv::Mat::ones(2, 2, CV_8UC3);

cv Mat给其中整行或整列赋值(使用copyTo函数):
把c的第一列赋值给a的第一列:

    Mat c = Mat::zeros(3, 5, CV_32F);Mat a = Mat::ones(3, 6, CV_32F);c.col(0).copyTo(a.col(0));//将c的1-5列赋值给ac.copyTo(a.colRange(1, 6));//pred_uvd_jts_29的第3列赋值给pred_xyz_jts_29的第3列pred_uvd_jts_29.col(2).copyTo(pred_xyz_jts_29.col(2));

colRange(start,end),包括左边界,不包括右边界,对rowRange同样适用。
3. cv Mat类型的取值方法
cv Mat类型是支持直接输出的:

//可以直接输出pred_uvd_jts_29矩阵的值
std::cout << "pred_uvd_jts_29 : " << pred_uvd_jts_29  << std::endl;

其他三种取值的方法:

Matname.at<float>(i, j);
Matname.ptr<float>(i)[j];
Matname.data;
cv::Mat camera_root(1, 3, CV_32FC1);
//代码实例
for(int i = 0; i < 29; i++)
{pred_xy_jts_29_meter.at<float>(i,0) = ((pred_uvd_jts_29.at<float>(i,0) + cx) * input_size / focal_length) * (pred_xyz_jts_29.at<float>(i, 2) * \depth_factor + pred_camDepth.at<float>(0, 0));pred_xy_jts_29_meter.at<float>(i,1) = ((pred_uvd_jts_29.at<float>(i,1) + cy) * input_size / focal_length) * (pred_xyz_jts_29.ptr<float>(i)[2] * \depth_factor + pred_camDepth.ptr<float>(0)[0]);pred_xyz_jts_29.at<float>(i,0) = pred_xy_jts_29_meter.at<float>(i,0) / depth_factor;pred_xyz_jts_29.at<float>(i,1) = pred_xy_jts_29_meter.at<float>(i,1) / depth_factor;
}
//camera_root为1行3列,给它的一行三个数赋值
camera_root.at<float>(0,0) = pred_xyz_jts_29.at<float>(0, 0) * depth_factor;
camera_root.at<float>(0,1) = pred_xyz_jts_29.at<float>(0, 1) * depth_factor;
camera_root.at<float>(0,2) = pred_xyz_jts_29.at<float>(0, 2) * depth_factor;
camera_root.at<float>(0,2) += pred_camDepth.at<float>(0, 0);

另外,几种取值的方法在debug和release模式下的时间不同,Debug模式下M.at(i, j)最耗时,用指针取值最快,在Release模式下,三者耗时相差不大,结果如下,感兴趣的小伙伴可以看看:穿越门
在这里插入图片描述
这里指针取值就是有一个Mat矩阵,根据Mat矩阵的属性行、列及通道数,将Mat拉成一行进行取值,具体代码如下:

cv::Mat feature = this->output[nodes_name[i]];//feature即得到onnx对应节点的输出
if (nodes_name[i] == "pred_xyz_jts_29")
{auto* pred_xyz_jts_29 = feature.ptr<float>();//定义一个auto指针类型//根据Mat的rows、cols及channels属性确定元素个数size_t pred_xyz_jts_29_out_length = feature.rows * feature.cols * feature.channels();for (int j = 0; j < pred_xyz_jts_29_out_length; j++)//遍历即可{std::cout << "pred_xyz_jts_29 " << j << "," << pred_xyz_jts_29[j] << std::endl;}
}
  1. cv Mat类型做归一化操作(减均值、除方差)
    我的预处理是先做了一个to_tensor操作,然后减mean,除std
img = im_to_torch(img)
# mean
img[0].add_(-0.406)
img[1].add_(-0.457)
img[2].add_(-0.480)# std
img[0].div_(0.225)
img[1].div_(0.224)
img[2].div_(0.229)

首先数学上这两个操作可以合并,最后只减一次均值和方差即可,计算合并后:
在这里插入图片描述

cv::Mat input_f;
input.convertTo(input_f, CV_32FC3);//input是处理完的U8C3类型要先convertTo转换成浮点型
input_f = input_f - cv::Scalar(103.53, 116.535, 122.4);//用scalar,对应通道减去计算出的均值
vector<float> v_std = {57.375, 57.12, 58.395};
std::vector<cv::Mat> planes(3);//planes是个长度为3的vector,里面每个元素类型都是cv Mat
cv::split(input_f, planes);//三通道的input_f按通道分割,结果存放在事先声明的planes中
cv::Mat planer;
for (int i = 0; i < 3; i++)
{cv::Mat f;planes[i].convertTo(f, CV_32FC1, 1.0 / v_std[i] );//除方差planer.push_back(f.reshape(1,1));//f.reshape(1,1)将矩阵转换成一个列向量,维度(row*col, 1)
}//planer.size():[65536*3]

注意:Mat.convertTo()方法在转换类型的同时可以做一些转换操作,原型是:

src.convertTo(dst, type, scale, shift)

scale是要乘上的比例因子,shift是要加上的类似偏置, 如果scale=1,shift=0,则不进行比例缩放:
dst(i)=src(i) x scale + shift
所以除255的操作可以写成:

image.convertTo(src_f, CV_32F, 1.0/255, 0);//图像大小没有变化,类型从UINT8变为了FLOAT32位

cv::split和cv::merge的原型:

void cv::split(
const cv::Mat& mtx, //输入图像
vector<Mat>& mv // 输出的多通道序列(n个单通道序列)
);
void merge(const vector<cv::Mat>& mv, // 输入的多通道序列(n个单通道序列)cv::OutputArray dst // 输出图像,包含mv
);

opencv相关函数可以学习博客:https://www.cnblogs.com/yanghailin/p/12067239.html#3-c-opencv%E7%9B%B4%E6%8E%A5%E5%87%8F%E5%9D%87%E5%80%BC–%E9%99%A4%E6%96%B9%E5%B7%AE
opencv的总结就到这里了,知道的越多,自己不知道的越多,书到用时方恨少,希望自己能不断积累,早日从菜鸡像不那么菜的菜鸡进化,加油喔~~~~~


http://www.ppmy.cn/news/142745.html

相关文章

尾行注释转行上注释 正则表达式

尾行注释转行上注释 正则表达式 匹配 ( *)(.;)( *// *)(.) 替换为 $1// $4\n$1$2

space-between时尾行排版优化

在使用justify-content: space-between;时,经常会遇到下列问题, ul {width: 500px;height: 500px;display: flex;justify-content: space-between;flex-wrap: wrap;}li {width: 130px;list-style: none;background-color: pink;height: 30px;margin: 20px 0;}ul:last-child::af…

vi中跳到首行或尾行

跳到首行&#xff1a;gg 跳到尾行&#xff1a;G

git 提交代码防止尾行序列LF转为CRLF

在Windows下默认的尾行序列是CRLF&#xff0c;在使用git提交代码时会将LF转为CRLF 通过一下设置保证在文件提交到版本库的时候文件的尾行序列不发生变化 git config --global core.autocrlf false有关尾行序列设置方式&#xff1a; vscode > 设置 > 搜索 eol&#xf…

115://开头的链接怎么下载?

115://开头的链接怎么下载&#xff1f;想要下载115://开头的链接&#xff0c;需要借助115浏览器。确定安装好115浏览器就按照下面的操作步骤来进行吧。 115://开头的链接下载方法介绍 1、登录115官网&#xff0c;下载115浏览器并安装; 2、在115浏览器地址栏输入&#xff1a;chr…

windbg preview下载及其历史版本下载

WinDBG是专门针对Windows NT系列操作系统而设计的调试器。WinDBG的最初版本是微软公司在开发最初Windows NT操作系统&#xff08;NT3.1&#xff09;期间推出的&#xff0c;它是当时NT团队内部开发和调试NT操作系统的最主要工具。WinDBG与NT系列操作系统有着密不可分的联系。Win…

ONNX安装

前言 以下均用清华镜像源安装&#xff0c;官网太慢。 CPU和GPU版&#xff0c;只能安装一个&#xff0c;建议安装 GPU 版。 安装时一定要注意与CUDA、cuDNN版本适配问题&#xff0c;具体适配列表参考&#xff1a;CUDA Execution Provider 安装 onnx pip install onnx -i http…

Linux使用Aria2命令下载BT种子/磁力/直链文件

文章目录 安装BT下载使用aria2c -S 009.torrent 列出种子内容aria2c xxx.torrnet 限速下载多线程下载功能 安装 yum install aria2 BT下载使用 aria2c -S 009.torrent 列出种子内容 ⚡ rootninesun  /home/vagrant aria2c -S CentOS-7-x86_64-Everything-2009.torrent &g…