#include "stdafx.h"
#include "funtions.h"
#include <stdio.h>
using namespace std;
int readImage()
{
std::cout << "-----------start to read Image-------------" << std::endl;
//读入单张图片,路径可替换成自己的图片的路径
cv::Mat srcMat = imread("../testImages\\butterfly.jpg");
//读取图片的一些信息
// Mat是否为空,可以判断读图是否成功
std::cout << "empty:" << (srcMat.empty() ? "the Mat is empty,fail to read" : "not empty") << std::endl;
if (srcMat.empty())return -1;
//在Mat中
//cols 是 列数 相当于 width
//rows 是 行数 相当于 height
//行数
std::cout << "rows:" << srcMat.rows << std::endl;
//列数
std::cout << "cols:" << srcMat.cols << std::endl;
//维度,普通图片为2维
std::cout << "dims:" << srcMat.dims << std::endl;
// Size是OpenCV内部定义的数据类型
std::cout << "size[]:" << srcMat.size().width << "," << srcMat.size().height << std::endl;
// 深度id
// 用来度量每一个像素中【每一个通道】的精度,depth数值越大,精度越高。在
//Opencv中,Mat.depth()得到的是一个0~6的数字,分别代表不同的位数,对应关系如下:
//opencv中,由于使用Mat.at访问数据时,必须正确填写相应的数据类型,
//Mat的类型定义方法
//The definition is as follows:
//CV_(位) + (数据类型) + (通道数量)
//如, CV_32FC1 表示 32位 float型单通道,
//OpenCV中的数据类型与C的数据类型的对应关系。
/*
uchar CV_8U 0
char CV_8S 1
ushort CV_16U 2
short CV_16S 3
int CV_32S 4
float CV_32F 5
double CV_64F 6
*/
std::cout << "depth (ID):" << srcMat.depth() << std::endl;
// channel数,如灰度图为单通道,RGB图为3通道
std::cout << "channels:" << srcMat.channels() << std::endl;
// Mat中一个元素的size(byte数),矩阵一个元素占用的字节数,
//数据类型是
//CV_8UC1, elemSize==1,1 byte;
//CV_8UC3/CV_8SC3, elemSize==3;3 byte
//CV_16UC3/CV_16SC3, elemSize==6;6 byte
//即elemSize==字节数x通道数;矩阵一个元素占用的字节数,
std::cout << "elemSize:" << srcMat.elemSize() << "[byte]" << std::endl;
// Mat中一个元素的一个通道的size(byte数),矩阵元素一个通道占用的字节数,
//eleSize1==elemSize/channels;
std::cout << "elemSize1 (elemSize/channels):" << srcMat.elemSize1() << "[byte]" << std::endl;
//元素的总数,如果是图像,即为像素个数
std::cout << "total:" << srcMat.total() << std::endl;
// step (byte数)
//Mat矩阵中每一行的“步长”,以字节为基本单位,每一行中所有元素的字节总量
//cols*elemSize=cols*eleSize1*channels
std::cout << "step:" << srcMat.step << "[byte]" << std::endl;
// 一个step的channel总数,每行的channel数
std::cout << "step1 (step/elemSize1):" << srcMat.step1() << std::endl;
// 该Mat在内存上是否连续
std::cout << "isContinuous:" << (srcMat.isContinuous() ? "true" : "false") << std::endl;
// 是否为子矩阵
std::cout << "isSubmatrix:" << (srcMat.isSubmatrix() ? "true" : "false") << std::endl;
//读入单张图片,加参数0,表示读入,并转换成灰度图
cv::Mat gryMat = imread("../testImages\\butterfly.jpg", 0);
if (srcMat.empty())return -1;
//保存图片
imwrite("../testImages\\gray-butterfly.jpg",gryMat);
//显示图片
imshow("src", srcMat);
imshow("gray", gryMat);
//显示图片,必须要加waitKey(),否则无法显示图像
//waitKey(0),无限地显示窗口,直到任何按键按下
//如果是其他数字,如waitKey(25)表示25毫秒,然后关闭。
waitKey(0);
//关闭所有窗口
destroyAllWindows();
return 0;
}
//通过OpenCV读取视频
int readVideo()
{
std::cout << "-----------start to read Video-------------" << std::endl;
//读取本地视频,OpenCV可以读取本地视频文件,摄像头,及连续的图像文件
//VideCapture为opencv定义的视频数据的类,实际是底层对ffmpeg的封装实现的
//----------------------读取视频文件--------------------------
//实例化VideoCapture类,名为cap,并打开()中的视频
//也可以通过 capVideo.open("../testImages\\vtest.avi"); 打开
//如果 capVideo.open(0)则打开默认摄像头,参数0为摄像头的id
VideoCapture capVideo("../testImages\\vtest.avi");
//如果视频打开失败
if (!capVideo.isOpened()) {
std::cout << "Unable to open video!" << std::endl;
return -1;
}
//读取视频的一些属性,更多参数可参考videoio_c.h中得定义
cout << "parameters" << endl;
cout << "width:" << capVideo.get(CV_CAP_PROP_FRAME_WIDTH) << endl;
cout << "heigth:" << capVideo.get(CV_CAP_PROP_FRAME_HEIGHT) << endl;
cout << "frames:" << capVideo.get(CV_CAP_PROP_FRAME_COUNT) << endl;
cout << "fps:" << capVideo.get(CV_CAP_PROP_FPS) << endl;
//保存文件初始化,VideoWriter为OpenCV中定义的视频保存类
VideoWriter writer;
//选择编码方式
int codec = CV_FOURCC('M', 'J', 'P', 'G');
// 输出的视频地址及名字
string filename = "../testImages\\saved.avi";
//定义帧率
double fps = capVideo.get(CV_CAP_PROP_FPS);
//保存的视频的尺寸,此处尺寸缩小一半
cv::Size vSize;
vSize.width = capVideo.get(CV_CAP_PROP_FRAME_WIDTH) / 2;
vSize.height = capVideo.get(CV_CAP_PROP_FRAME_HEIGHT) / 2;
//打开视频流
writer.open(filename, codec, fps, vSize);
Mat frame;
Mat resizeFrame;
Mat grayFrame;
while (1) {
//视频流中读取图像
capVideo >> frame;
if (frame.empty()) {
cout << "Unable to read frame!" << endl;
destroyAllWindows();
return -1;
}
//保存到视频流,由于视频文件尺寸降为1/2,frame尺寸也要减半
resize(frame,resizeFrame,vSize);
writer.write(resizeFrame);
//可以接各种处理
cvtColor(frame, grayFrame, CV_RGB2GRAY);
imshow("frame",frame);
imshow("resizeFrame",resizeFrame);
imshow("gray",grayFrame);
//显示图片,延时30ms,必须要加waitKey(),否则无法显示图像
//等待键盘相应,按下ESC键退出
if (waitKey(30) == 27){
destroyAllWindows();
break;
}
}
destroyAllWindows();
return 0;
}
//读取连续图片
int readSequence()
{
//(eg. `img_%02d.jpg`, which will read samples like `img_00.jpg, img_01.jpg, img_02.jpg, ...`)
VideoCapture capSequence("../testImages\\sequence\\left%02d.jpg");
if (!capSequence.isOpened())
{
cerr << "Unable to open the image sequence!\n" << endl;
return 1;
}
cv::Mat frame;
while (1) {
//视频流中读取图像
capSequence >> frame;
if (frame.empty()) {
cout << "Unable to read frame!" << endl;
destroyAllWindows();
return -1;
}
imshow("frame", frame);
waitKey(200);
}
return 0;
}
//Mat类的创建方法,及初始化示例
int createMat()
{
//---创建Mat---
//cols 是 列数 相当于 width
//rows 是 行数 相当于 height
int cols = 4;
int rows = 3;
int type = CV_32S;
int dataArray[] = { 0, 1, 2, 3,
10, 11, 12, 13,
10, 11, 12, 13 };
cv::Mat mat1_0; //实例化,此操作并不在内存上开辟空间
cv::Mat mat2; //实例化,此操作并不在内存上开辟空间
cv::Mat mat3; //实例化,此操作并不在内存上开辟空间
//几种方法,进行初始化定义尺寸和类型,并开辟空间
mat1_0.create(rows, cols, type);
mat2.create(Size(cols, rows), type);
mat3.create(mat1_0.size(), mat1_0.type());
//通过指针对mat1初始化
cv::Mat mat1_1(rows, cols, CV_32S, &dataArray);
//如果mat1的保存空间连续,则拷贝数组的数据给mat1
//Mat的数据实际保存在成员数组 data 里面
if (mat1_0.isContinuous()) {
memcpy(mat1_0.data, dataArray, sizeof(int)*cols*rows);
}
//生成随机数
//均一分布的随机数,[0,256)
cv::randu(mat2, cv::Scalar(0), cv::Scalar(256));
// 正太分布的随机数,mean=128, stddev=10
cv::randn(mat3, cv::Scalar(128), cv::Scalar(10));
std::cout << "m1_0:" << std::endl << mat1_0 << std::endl << std::endl;
std::cout << "m1_1:" << std::endl << mat1_1 << std::endl << std::endl;
std::cout << "m2:" << std::endl << mat2 << std::endl << std::endl;
std::cout << "m3:" << std::endl << mat3 << std::endl << std::endl;
//---创建Mat---
// 创建数据类型为64F, channels=10, 3x3 的2维矩阵
cv::Mat mat4(3, 3, CV_64FC(10));
//也可以通过CV_MAKETYPE()获得赋值的参数,本例中CV_MAKETYPE(CV_64F, 10)==78
cv::Mat mat5(3, 3, CV_MAKETYPE(CV_64F, 10));
//创建channels=2,int型,2x2矩阵,并赋值,其他数据类型可查matx.hpp中的定义
cv::Mat mat6 = (cv::Mat_<cv::Vec2i>(2, 2) << cv::Vec2i(1, 1), cv::Vec2i(2, 4),
cv::Vec2i(3, 9), cv::Vec2i(4, 16));
std::cout << "m6:" << std::endl << mat6 << std::endl << std::endl;
// 5×4矩阵, 5行×4列,元素均为1
cv::Mat mat7 = cv::Mat::ones(5, 4, CV_8U);
// 5×4矩阵, 5行×4列,元素均为3
cv::Mat mat8 = cv::Mat::ones(5, 4, CV_8U) * 3;
// 5×4矩阵, 5行×4列,元素均为0
cv::Mat mat9 = cv::Mat::zeros(5,4, CV_8U);
// 3×3矩阵, 3行×3列,单位矩阵
cv::Mat mat10 = cv::Mat::eye(3, 3, CV_8U);
std::cout << "m7:" << std::endl << mat7 << std::endl << std::endl;
std::cout << "m8:" << std::endl << mat8 << std::endl << std::endl;
std::cout << "m9:" << std::endl << mat9 << std::endl << std::endl;
std::cout << "m10:" << std::endl << mat10 << std::endl << std::endl;
return 0;
}
//Mat的复制方法
//Mat的复制,有深复制及浅复制的分别
int copyMat()
{
//生成一个3×3的Mat
cv::Mat m1 = (cv::Mat_<double>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
//浅复制,实质只是把m1的内存地址赋值给m_shallow
//两个Mat在内存中是同一块数据
cv::Mat m_shallow = m1;
//深复制,clone和copyTo,为m_deep1及m_deep2在内存中开辟空间,并且复制内容
cv::Mat m_deep1 = m1.clone();
cv::Mat m_deep2;
m1.copyTo(m_deep2);
std::cout << "m1=" << m1 << std::endl << std::endl;
std::cout << "m_shallow=" << m_shallow << std::endl << std::endl;
std::cout << "m_deep1=" << m_deep1 << std::endl << std::endl;
std::cout << "m_deep2=" << m_deep2 << std::endl << std::endl;
// 修改m1的(0,0)位置的数值,注意观察修改以后,其他几个Mat的内容
m1.at<double>(0, 0) = 100;
std::cout << "m1=" << m1 << std::endl << std::endl;
std::cout << "m_shallow=" << m_shallow << std::endl << std::endl;
std::cout << "m_deep1=" << m_deep1 << std::endl << std::endl;
std::cout << "m_deep2=" << m_deep2 << std::endl << std::endl;
//定义ROI并复制
//ROI(region of interest)感兴趣区域,即需要被处理的区域
//Rect是opencv中定义的矩形数据类型
//读入单张图片,路径可替换成自己的图片的路径
cv::Mat srcMat = imread("../testImages\\butterfly.jpg");
cv::Mat roiMat;
cv::Rect roi;
roi.x = 0;
roi.y = 0;
roi.width = srcMat.cols / 2;
roi.height = srcMat.rows / 2;
//定义mask并复制
//mask即遮罩,用来屏蔽掉图像中的部分区域
//mask的格式为uchar格式的mat,黑色部分表示需要屏蔽的,白色表示不需要遮蔽
//生成mask
cv::Mat mask= cv::Mat::zeros(srcMat.size(), CV_8U);
rectangle(mask,roi,Scalar(255),-1);
cv::Mat maskedMat;
//复制ROI区域
srcMat(roi).copyTo(roiMat);
//带mask复制
srcMat.copyTo(maskedMat, mask);
imshow("src",srcMat);
imshow("mask",mask);
imshow("masked image",maskedMat);
imshow("roi",roiMat);
waitKey(0);
return 0;
}
//利用Mat进行一些基本运算
int calcMat()
{
//创建Mat
cv::Mat m1 = (cv::Mat_<double>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
std::cout << "m1=" << m1 << std::endl << std::endl;
//基本四则运算
cv::Mat m2 = m1 + 3;
cv::Mat m3 = m1 * 3;
cv::Mat m4 = m1 / 3;
std::cout << "m2=" << m2 << std::endl << std::endl;
std::cout << "m3=" << m3 << std::endl << std::endl;
std::cout << "m4=" << m4 << std::endl << std::endl;
//mat和mat的运算
cv::Mat m5 = m1 + m1;
//m6和m2相同位置的数值相乘
cv::Mat m6 = m1.mul(m2);
//相乘后,再乘以系数
cv::Mat m7 = m1.mul(m2, 2);
std::cout << "m5=" << m5 << std::endl << std::endl;
std::cout << "m6=" << m6 << std::endl << std::endl;
std::cout << "m7=" << m7 << std::endl << std::endl;
//要确保运算Mat的类型和尺寸相同,如果不同,则抛出异常
//Mat类型不同
cv::Mat m8 = (cv::Mat_<int>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
try {
std::cout << m1 / m8 << std::endl;
}
catch (cv::Exception e) {
std::cout << std::endl;
}
//Mat的尺寸不同
cv::Mat m9 = (cv::Mat_<double>(2, 2) << 1, 2, 3, 4);
try {
std::cout << m9 / m1 << std::endl;
}
catch (cv::Exception e) {
// ...
std::cout << std::endl;
}
return 0;
}
//一些基本的线性代数操作
int calcLinearAlg()
{
//向量的內积和外积
cv::Vec3d v1(1, 2, 3);
cv::Vec3d v2(3, 4, 5);
//內积
double v_dot = v1.dot(v2);
//外积
cv::Vec3d v_cross = v1.cross(v2);
std::cout << "v_dot=" << v_dot << std::endl;
cv::Mat tmp(v_cross);
std::cout << "v_cross=" << tmp << std::endl;
//求范数
// 6x1
cv::Mat m1 = (cv::Mat_<double>(6, 1) << 1, 5, 3, -1, -3, -5);
// 向量(3,4)
cv::Point p1(3, 4);
// 6维度向量的 L-2范数
double norm_m1 = cv::norm(m1);
// 2维度向量的 L-2范数
double norm_p1 = cv::norm(p1);
std::cout << std::endl;
std::cout << "norm(m1)=" << norm_m1 << std::endl;
std::cout << "norm(p1)=" << norm_p1 << std::endl << std::endl;
// 通过2维坐标,计算极坐标,即大小和角度
std::cout << "calc Polar" << std::endl;
//创建4组2维坐标
cv::Mat x = (cv::Mat_<double>(4, 1) << 0, 1, 4, 1);
cv::Mat y = (cv::Mat_<double>(4, 1) << 1, 1, 3, 1.7320504);
cv::Mat magnitude, angle;
cv::cartToPolar(x, y, magnitude, angle, true);
for (int i = 0; i<4; ++i) {
std::cout << "(" << x.at<double>(i) << ", " << y.at<double>(i) << ") ";
std::cout << "mag=" << magnitude.at<double>(i) << ", angle=" << angle.at<double>(i) << "[deg]" << std::endl;
}
std::cout << std::endl;
// 通过大小和角度,计算2维坐标
std::cout << "calc Cartesian" << std::endl;
cv::Mat mag2 = (cv::Mat_<double>(4, 1) << 1, 1.41421, 5, 2);
cv::Mat ang2 = (cv::Mat_<double>(4, 1) << 90, 45, 36.8699, 60);
cv::Mat x2, y2;
cv::polarToCart(mag2, ang2, x2, y2, true); // in degrees
for (int i = 0; i<4; ++i) {
std::cout << "(" << x2.at<double>(i) << ", " << y2.at<double>(i) << ") ";
std::cout << "mag=" << mag2.at<double>(i) << ", angle=" << ang2.at<double>(i) << "[deg]" << std::endl;
}
std::cout << std::endl;
return 0;
}
//求解线性方程
int solveLinearEquations()
{
//独立方程数和未知数相同时
// x + y + z = 6
// 3x + 2y - 2z = 1
// 2x - y + 3z = 9
//左边
cv::Mat lhand = (cv::Mat_<double>(3, 3) << 1, 1, 1, 3, 2, -2, 2, -1, 3);
//右边
cv::Mat rhand = (cv::Mat_<double>(3, 1) << 6, 1, 9);
//高斯消去法求解
cv::Mat ans;
cv::solve(lhand, rhand, ans);
std::cout << "Gaussian elimination" << std::endl;
std::cout << "(x,y,z) = " << ans << std::endl << std::endl;
//独立方程数 多于 未知数数量时
//通过最小二乘法求解
// x + y = 3
// 3x + 4y = 8
// -x - 2y = 2
std::cout << "the least square method" << std::endl;
cv::Mat lhand2 = (cv::Mat_<double>(3, 2) << 1, 1, 3, 4, -1, -2);
cv::Mat rhand2 = (cv::Mat_<double>(3, 1) << 3, 8, 2);
cv::Mat x;
//通过SVD求解最小二乘法
//方程组左侧,方程组右侧,输出,求解方法
cv::solve(lhand2, rhand2, x, cv::DECOMP_SVD);
std::cout << "(x,y) = " << x << std::endl;
std::cout << "norm(lhand2*x-rhand2)=" << norm(lhand2*x - rhand2) << std::endl << std::endl;
return 0;
}
opencv 一些基础代码
猜你喜欢
转载自blog.csdn.net/weixin_63163242/article/details/131677848
今日推荐
周排行