这是本人第一次上手OpenCV,初期开始就遇到配置OpenCV的环境花费很久时间;下面是我在完成环境配置后,第一次在vs20010上实现了对图像的读写操作及视频读写操作的源码。
#include <iostream>
#include <opencv2/opencv.hpp>
#include "highgui.h"
/************************************************************************/
/* opencv版本对应相应的vs版本 */
/*在vs2010上配置opencv2.4.10 */
/*DEMO */
/************************************************************************/
using namespace std;
using namespace cv;
bool MatReadingImage();
bool IplImageReadingImage();
bool AtDemo();
bool IteratorDemo();
bool IplImageDemo();
bool WriteImage();
bool ReadingVideo();
bool WriterVideoDemo();
int main(int argc ,char * argv[])
{
if (MatReadingImage())
{
cout << "调用函数成功!!!" << endl;
}else{
cout << "调用函数失败!!!" << endl;
}
return 0;
}
bool MatReadingImage()
{
//Mat 类
const char* imagename = "lena.png";
//从文件中读入图像
Mat img = imread(imagename); //读取图像(可以转换图像的通道)
//如果读入图像失败
if(img.empty())
{
fprintf(stderr, "Can not load image %s\n", imagename);
return false;
}
//显示图像
imshow("image",img);
waitKey(0);
return true;
}
bool IplImageReadingImage()
{
IplImage *src;
src = cvLoadImage("lena.png"); //这里将lena.png和TestOpenCV.cpp文件放在同一个文件夹下
cvNamedWindow("lena",CV_WINDOW_AUTOSIZE);
cvShowImage("lena",src);
waitKey(0);
cvDestroyWindow("lena");
cvReleaseImage(&src);
return true;
/*
*早期使用 IplImage 和 CvMat 数据结构来表示图像;都是C语言结构(内存需要手动管理)
*
*
*/
}
bool AtDemo()
{
//使用at()函数遍历;代码可读性高,效率不高
Mat grayim (600,800,CV_8UC1); //创建行数(rows)为3,列数(cols)为2,通道数(3C)为3的图像(8U表示8位无符号整数);像素值初始化为0,0,255;默认颜色顺序是BGR
Mat colorim(600, 800,CV_8UC3);
for(int i = 0; i < grayim.rows; ++i)
{
for (int j = 0; j < grayim.cols; ++j)
{
grayim.at<uchar>(i,j) = (i +j) % 255;
}
}
for(int i = 0; i < colorim.rows; ++i)
{
for (int j = 0; j < colorim.cols; ++j)
{
Vec3b pixel;
pixel[0] = i % 255; //bule
pixel[1] = j % 255; //green
pixel[2] = 0; //red
colorim.at<Vec3b>(i , j) = pixel;
}
}
imshow("grayim",grayim);
imshow("colorim",colorim);
waitKey(0);
return true;
}
bool IteratorDemo()
{
//迭代器(iterator),方便遍历所有元素
Mat grayim (600,800,CV_8UC1);
Mat colorim(600, 800,CV_8UC3);
//遍历所有的像素,并设置像素值
MatIterator_<uchar> grayit, grayend;
for ( grayit = grayim.begin<uchar>(), grayend = grayim.end<uchar>();grayit != grayend ; ++grayit)
{
*grayit = rand() % 255;
/*
*
*单通道的图设置像素值
*
*/
}
MatIterator_<Vec3b> colorit , colorend;
for (colorit = colorim.begin<Vec3b>(), colorend = colorim.end<Vec3b>(); colorit != colorend ; ++colorit)
{
(*colorit)[0] = rand() % 225;
(*colorit)[1] = rand() % 225;
(*colorit)[2] = rand() % 225;
/*
*
*三通道的图设置像素值
*
*/
}
imshow("grayim",grayim);
imshow("colorim",colorim);
waitKey(0);
return true;
}
bool IplImageDemo()
{
//使用IplImage结构时,使用数据指针来直接操作像素(非常高效易出错)
Mat grayim (600,800,CV_8UC1);
Mat colorim(600, 800,CV_8UC3);
for(int i = 0; i < grayim.rows; ++i)
{
uchar * p = grayim.ptr<uchar>(i);
//获取第i行首像素指针
for (int j = 0; j < grayim.cols; ++j)
{
//对第i行的每个像素(byte)进行操作
p[j] = (i +j) % 255;
}
}
for(int i = 0; i < colorim.rows; ++i)
{
Vec3b * pixel = colorim.ptr<Vec3b>(i);
for (int j = 0; j < colorim.cols; ++j)
{
pixel[j][0] = i % 255; //bule
pixel[j][1] = j % 255; //green
pixel[j][2] = 0; //red
}
}
imshow("grayim",grayim);
imshow("colorim",colorim);
waitKey(0);
return true;
}
bool WriteImage()
{
//将图像写入文件
//bool imwrite(const string & filename, InputArray image, const vector<int>& params = vector<int>())
Mat img = imread("lena.png",0);
if (img.empty())
{
cout << "Can not load imge." << endl;
}
Mat result,lena_huidu;
lena_huidu = img;
Canny(img, result ,50 ,150);
imwrite("lena_canny.png",result);
imwrite("lena_huidu.png",lena_huidu);
return true;
}
bool ReadingVideo()
{
/*读视频
*读视频VideoCapture既可以从视频读取图像,也可以从摄像头读取图像
*使用该类的构造函数打开视频文件或者摄像头
*如果VideoCapture对象已经创建可以使用VideoCapture::open()打开
*
*如果要读一帧,可以使用VideoCapture::read()函数
*/
//打开第一个摄像头
//VideoCapture cap(0);//参数为零打开摄像头
//打开视频文件
VideoCapture cap("缘起 动画电影《白蛇缘起》推广曲 - 周深.mp4");
if (!cap.isOpened())
{
cerr << "Can not open a camera or file." << endl;
return false;
}
Mat frame;
//创建窗口
//namedWindow("frame",0);
for (;;)
{
//Mat frame;
//从cap中读一帧,存到frame
cap >> frame;
if (frame.empty())
{
break;
}
imshow("frame",frame);
if (waitKey(30) >= 0)
{
break;
}
}
return true;
}
bool WriterVideoDemo()
{
//写视频
//设置一系列参数,包括:文件名,编解码器,帧率,宽度,高度等
Size videoTest(1048,240);
//创建 writerVideo,并指出 fourcc 及 fps 等参数
VideoWriter writerVideo = VideoWriter("myvideo.avi",CV_FOURCC('M','J','P','G'),25,videoTest);
if (!writerVideo.isOpened())
{
cerr << "Can not create video file.\n" << endl;
return false;
}
//视频帧
Mat frame(videoTest,CV_8UC3);
for (int i = 0; i < 100; i++)
{
//将图像设置为黑色
frame = Scalar::all(255);
//将整数i转为i字符串类型
char iText[128];
_snprintf(iText,sizeof(iText),"hello word %d",i);
//将数字绘到画面上
putText(frame, iText, Point(videoTest.width / 3, videoTest.height / 3),
FONT_HERSHEY_SCRIPT_SIMPLEX, 3, Scalar(0, 0, 255), 3, 8);
//将图像写入视频
writerVideo << frame;
}
return true;
}
/*
*Mat 与 IplImage 和 CvMat 的转换
*
*1:Mat 转换为 IpLImage 和 CvMat 格式
* Mat img (size(320,240),CV_8UC3);
* IpLImage iplimg = img;(CvMat cvimg = img;) //转换为IpLImage(CvMat)结构
* mycvoldFunc(&iplimg, ...) //对iplimg取地址
*
* //不可将Mat数据提前释放
*
*2:IplImage 和 CvMat格式转为 Mat
*
* Mat类有两个构造参数,两个构造参数都有一个参数copyData。
* Mat::Mat(const CvMat* M, bool copyData = false)
* Mat::Mat(const IplImage* IplImage, bool copyData = false)
* if copyData的值是false
* Mat 将与 IplImage 和 CvMat 共用一矩阵数据;
* 共用数据;
* Mat 将不会使用计数器来管理内存,需要开发者自己来管理;
* if copyData的值是false
* Mat 会新申请内存;
* 将 IplImage 和 CvMat 的数据库复制到 Mat 的数据区;
* 内存管理将变得简单;
*
* 建议此转换使用TURE:
* IplImage * iplimg = cvLoadImage("lena.jog");
* Mat img(iplimg, ture);
*
*/