一张图片的组成
- 文件标识 + 数据块
- 文件标识: 文件签名 维数 高度 宽度 深度 通道数 颜色格式 数据首地址 结束地址 数据量等等
- 图像深度: 每个像素所用的比特数
- 图像通道数: 灰度图的通道数为1. 彩色图为3
opencv源码结构学习
opencv基本架构分析
Mat的操作例子
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
void info(){
std::cout<<"Please input parameter..."<<std::endl;
std::cout<<"1-Function:Create zeros mat with 1 channel"<<std::endl;
std::cout<<"2-Function:Create zeros mat with 3 channels"<<std::endl;
std::cout<<"3-Function:Input image and output matrix values"<<std::endl;
std::cout<<"4-Function:Copy a mat"<<std::endl;
std::cout<<"5-Function:Deep copy a mat data"<<std::endl;
std::cout<<"6-Function:Iterate pixels in a mat"<<std::endl;
std::cout<<"7-Function:Set ROI and editing"<<std::endl;
}
int main(int argc,char* argv[]){
//没有输入参数
if(argc==1){
info();
return 1;
}
switch(atoi(argv[1])){
case 1:
{
std::cout<<"Function 1 : Create zeros mat with 1 channel"<<std::endl;
//创建一个8*8,位数为8的单通道Mat
cv::Mat mat(8,8,CV_8UC1);
//将Mat置0,使得矩阵内所有像素值为0
mat.zeros(mat.size(),mat.type());
//输出矩阵结果
std::cout<<mat<<std::endl;
break;
}
case 2:
{
std::cout<<"Function 2 : Create zeros mat with 3 channels"<<std::endl;
//创建一个8*8,位数为8的三通道Mat
cv::Mat mat2(8,8,CV_8UC3);
//同样将Mat置0,使得矩阵内所有像素值为0
mat2.zeros(mat2.size(),mat2.type());
//输出效果,和单通道的矩阵相比,数据量是单通道的三倍
std::cout<<mat2<<std::endl;
break;
}
case 3:
{
std::cout<<"Function 3 : Input image and output matrix values"<<std::endl;
//输入一张图,尺寸为图片原来的尺寸
cv::Mat mat3 = cv::imread("lena.jpg");
//修改这个图片Mat的使用尺寸
cv::resize(mat3,mat3,cv::Size(8,8));
//输出所有像素值
std::cout<<mat3<<std::endl;
break;
}
case 4:
{
std::cout<<"Function 4 : Copy a mat"<<std::endl;
//输入一张图
cv::Mat mat4 = cv::imread("lena.jpg");
//浅拷贝一个Mat,浅拷贝只数据地址是公用的,所以修改其中一个Mat,两个Mat的值都会被修改
cv::Mat mat4_1 = mat4;
//垂直翻转图片
cv::flip(mat4_1,mat4_1,1);
//显示效果,两个Mat都被翻转了
cv::imshow("mat4",mat4);
cv::imshow("mat4_1",mat4_1);
cv::waitKey(0);
break;
}
case 5:
{
std::cout<<"Function 5 : Deep copy a mat data"<<std::endl;
//输入一张图片
cv::Mat mat5 = cv::imread("lena.jpg");
//深拷贝一个Mat,数据完全复制,没有共用的部分,所以修改任意一个Mat,互不影响
cv::Mat mat5_1;
mat5.copyTo(mat5_1);
//上下翻转矩阵
cv::flip(mat5_1,mat5_1,0);
//显示效果,只有一个是被翻转了,另个一不受影响
cv::imshow("mat5",mat5);
cv::imshow("mat5_1",mat5_1);
cv::waitKey(0);
break;
}
case 6:
{
std::cout<<"Function 6 : Iterate pixels in a mat"<<std::endl;
//输入一张图片
cv::Mat mat6 = cv::imread("lena.jpg");
//重新定义尺寸
cv::resize(mat6,mat6,cv::Size(8,8));
//遍历每一个像素的值,可以看到和Function3,输出的结果一致
for(int j=0;j<mat6.rows;j++){
for(int i=0;i<mat6.cols;i++){
std::cout<<(int)mat6.at<cv::Vec3b>(j,i)[0]<<", "<<(int)mat6.at<cv::Vec3b>(j,i)[1]<<", "<<(int)mat6.at<cv::Vec3b>(j,i)[2]<<", ";
}
std::cout<<std::endl;
}
break;
}
case 7:
{
std::cout<<"Function 7 : Set ROI and editing"<<std::endl;
//输入一张图片
cv::Mat mat7 = cv::imread("lena.jpg");
//设置ROI位置
cv::Rect roi(mat7.cols/4,mat7.rows/4,mat7.cols/2,mat7.rows/2);
cv::Mat mat7_roi = mat7(roi);
//垂直翻转,这时候,对ROI的任意操作都是在修改原图的基础上操作的
cv::flip(mat7_roi,mat7_roi,1);
//显示原图,ROI的部分被修改了
cv::imshow("mat7",mat7);
cv::waitKey(0);
break;
}
default:
{
info();
break;
}
}
return 0;
}
视频的读取与控制
- 视频相关操作使用的是:
cv::VideoCapture
- 获得视频的相关信息
eg.
获取当前视频帧率double rate = capture.get(CV_CAP_PROP_FPS);
获取总帧数:int frame_num = capture.get(CV_CAP_PROP_POS_FRAMES);
- 视频操作的框架代码
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
int main(int argc,char* argv[]){
//capture直接定义视频文件路径,如果路径设置为0,则读取电脑摄像头的数据
//cv::VideoCapture capture(0);
cv::VideoCapture capture(argv[1]);
if(!capture.isOpened()){
std::cout<<"video not open."<<std::endl;
return 1;
}
//获取当前视频帧率
double rate = capture.get(CV_CAP_PROP_FPS);
//当前视频帧
cv::Mat frame;
//每一帧之间的延时
//与视频的帧率相对应
int delay = 1000/rate;
bool stop(false);
while(!stop){
if(!capture.read(frame)){
std::cout<<"no video frame"<<std::endl;
break;
}
/*
*
* 此处为添加对视频的每一帧的操作方法
*
*/
cv::cvtColor(frame,frame,CV_RGB2GRAY);
cv::imshow("video",frame);
//引入延时
//也可通过按键停止
if(cv::waitKey(delay)>0)
stop = true;
}
//关闭视频,手动调用析构函数(非必须)
capture.release();
return 0;
}
- 保存视频:
VideoWriter
用来保存视频
cv::VideoWriter writer;
初始化: 要指定哪些数据呢?
writer.open("VideoOutput.avi",CV_FOURCC('M','J','P','G'),rate,cv::Size(frame.cols,frame.rows));
// 函数原型
CV_WRAP virtual bool open(const string& filename, int fourcc, double fps,Size frameSize, bool isColor=true);
- 输出文件名 格式 帧率 帧的大小 默认为彩色图
- 保存视频的源代码学习:
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main(int argc,char* argv[]){
cv::VideoCapture capture(argv[1]);
if(!capture.isOpened()){
std::cout<<"video not open."<<std::endl;
return 1;
}
//获取当前视频帧率
double rate = capture.get(CV_CAP_PROP_FPS);
//当前视频帧
cv::Mat frame;
//每一帧之间的延时
//与视频的帧率相对应
int delay = 1000/rate;
bool stop(false);
//创建VideoWriter做保存视频
cv::VideoWriter writer;
bool writer_init(false);
while(!stop){
if(!capture.read(frame)){
std::cout<<"no video frame"<<std::endl;
break;
}
if(!writer_init){
writer.open("VideoOutput.avi",CV_FOURCC('M','J','P','G'),rate,cv::Size(frame.cols,frame.rows));
writer_init = true;
}
/*
*
* 此处为添加对视频的每一帧的操作方法
*
*/
//写入保存视频
writer<<frame;
cv::imshow("video",frame);
//引入延时
//也可通过按键停止
if(cv::waitKey(delay)>0)
stop = true;
}
//关闭视频,手动调用析构函数(非必须)
capture.release();
return 0;
}