若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/100735114
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
上一篇:《OpenCV开发笔记(三):OpenCV图像的概念和基本操作》
下一篇:《OpenCV开发笔记(五):OpenCV读取与操作摄像头》
OpenCV对图像进行操作,图像包含图片和视频。
读取图像文件,使用的imread()。
imread()函数返回的是Mat对象,如果读取函数文件失败,会返回一个空矩阵(常量cv::Mat::data变量的值是NULL)。
Mat imread(const string& filename, int flags=1 )
flag>0,该函数返回3通道图像,如果磁盘上的图像文件是单通道的灰度图像,则会被强制转为3通道;
flag=0,该函数返回单通道图像,如果磁盘的图像文件是多通道图像,则会被强制转为单通道;
flag<0,则函数不对图像进行通道转换。
imread()函数支持多种文件格式,且该函数是根据图像文件的内容来确定文
件格式,而不是根据文件的扩展名来确定。
支持的图像格式:bmp、dib、jpg、jpeg、jpe、png、pbm、pgm、ppm、sr、ras、tiff、tif、exr、jp2。(需要对应的库支持,开发使用的库要编译时添加进去,然后编译生成opencv库)
保存图像文件,使用的imwrite()。
imwrite()函数返回的是bool。
bool imwrite(const string& filename,
InputArray image,
const vector& params=vector())
filename是存成指定的文件名,注意格式是由指定的文件扩展名确定。
PNG-是无损压缩格式,推荐使用。
BMP-格式是无损格式,但是一般不进行压缩,文件尺寸非常大;
JPEG-格式的文件娇小,但是JPEG是有损压缩,会丢失一些信息。
并不是所有的 Mat 对象都可以存为图像文件,目前支持的格式只有8U类型的单通道和3通道(颜色顺序为 BGR)矩阵;如果需要要保存16U格式图像, 只能使用PNG、JPEG 2000和TIFF格式。
如果希望将其他格式的矩阵保存为图像文件,可以先用Mat::convertTo()函数或者cvtColor()函数将矩阵转为可以保存的格式。
注意:在保存文件时,如果文件已经存在,imwrite()函数不会进行提醒,将直接覆盖掉以前的文件。
#if TEST_IMAGE
// 读取
cv::Mat image = cv::imread("1.jpg");
// 判断是否读取成功
if(image.data == NULL)
{
QMessageBox::warning(0, "读取图片失败", "1.jpg");
return;
}
// 显示
cv::imshow("readImage", image);
// 作一个图像行列转换操作,再保存
image = image.t();
// 保存
if(!cv::imwrite("1 to 2.jpg", image))
{
QMessageBox::warning(0, "保存失败", "1.jpg");
return;
}
#endif
图像文件,可以根据文件扩展名得知图像的格式。但是此经验并不能推广到视频文件中。有时候会碰到奇怪的问题,都是avi视频文件,有的能用OpenCV打开,有的不能。
视频的格式主要由压缩算法决定,就是视频编解码器。视频文件能读或者写,关键看是否有相应的编解码器。
OpenCV 2中提供了两个类来实现视频的读写。读视频的类是VideoCapture,写视频的类是VideoWriter。
VideoCapture 既可以从视频文件读取图像,也可以从摄像头读取图像。可以使用该类的构造函数打开视频文件或者摄像头。如果 VideoCapture 对象已经创建,也可以使用VideoCapture::open()打开,VideoCapture::open()函数会自动调用VideoCapture::release()函数,先释放已经打开的视频,然后再打开新视频。
使用OpenCV创建视频与读视频不同的是,需要在创建视频时设置一系列参数,包括:文件名,编解码器,帧率,宽度和高度等。
编解码器使用四个字符表示,可以是:
如果使用某种编解码器无法创建视频文件,请尝试其他的编解码器。
将图像写入视频可以使用VideoWriter::write()函数,VideoWriter类中也重载了<<操作符,使用起来非常方便。另外需要注意:待写入的图像尺寸必须与创建视频时指定的尺寸一致。
#if TEST_VIDEO
cv::VideoCapture videoCapture;
// 打开视频
if(!videoCapture.open("1.mp4"))
{
QMessageBox::warning(0, "读取视频失败", "1.mp4");
return;
}
int width = 0;
int height = 0;
for(;;)
{
cv::Mat frame;
videoCapture >> frame;
// 第一次进入,记录视频尺寸
if(width == 0)
{
width = frame.cols;
height = frame.rows;
}
// 最后一帧之后为空,退出
if(frame.empty())
{
break;
}
// 显示
cv::imshow("readVideo", frame);
// 等待1s,有按键输入立即结束本次
if(cv::waitKey(1) >= 0)
break;
}
// 将视频输入流返回到第0帧
videoCapture.set(cv::CAP_PROP_POS_FRAMES, 0);
cv::VideoWriter videoWrite;
// 翻转操作了
width = width + height;
height = width - height;
width = width - height;
if(!videoWrite.open("1 to 1.avi", CV_FOURCC('M','J','P','G'), 25, cv::Size(width, height)))
{
QMessageBox::warning(0, "保存视频失败", "1 to 1.avi");
return;
}
QString version = "v1.3.0";
QString text = QString("OpenCVDemo %1 QQ21497936 blog.csdn.net/qq21497936").arg(version);
for(;;)
{
cv::Mat frame;
videoCapture >> frame;
if(frame.empty())
{
break;
}
// 沿对角线行列翻转
frame = frame.t();
cv::putText(frame,
cv::String(text.toUtf8().data()),
cv::Point(0, height / 2),
cv::FONT_HERSHEY_SCRIPT_SIMPLEX,
0.8,
cv::Scalar(0,0,255),
3,
8,
false);
cv::imshow("readVideo", frame);
videoWrite << frame;
if(cv::waitKey(1) >= 0)
break;
}
#endif
然后
void OpenCVManager::testImageAndVideo()
{
#define TEST_IMAGE (0)
#define TEST_VIDEO (1)
#if TEST_IMAGE
// 读取
cv::Mat image = cv::imread("1.jpg");
// 判断是否读取成功
if(image.data == NULL)
{
QMessageBox::warning(0, "读取图片失败", "1.jpg");
return;
}
// 显示
cv::imshow("readImage", image);
// 作一个图像行列转换操作,再保存
image = image.t();
// 保存
if(!cv::imwrite("1 to 2.jpg", image))
{
QMessageBox::warning(0, "保存失败", "1.jpg");
return;
}
#endif
#if TEST_VIDEO
cv::VideoCapture videoCapture;
// 打开视频
if(!videoCapture.open("1.mp4"))
{
QMessageBox::warning(0, "读取视频失败", "1.mp4");
return;
}
int width = 0;
int height = 0;
for(;;)
{
cv::Mat frame;
videoCapture >> frame;
// 第一次进入,记录视频尺寸
if(width == 0)
{
width = frame.cols;
height = frame.rows;
}
// 最后一帧之后为空,退出
if(frame.empty())
{
break;
}
// 显示
cv::imshow("readVideo", frame);
// 等待1s,有按键输入立即结束本次
if(cv::waitKey(1) >= 0)
break;
}
// 将视频输入流返回到第0帧
videoCapture.set(cv::CAP_PROP_POS_FRAMES, 0);
cv::VideoWriter videoWrite;
// 翻转操作了
width = width + height;
height = width - height;
width = width - height;
if(!videoWrite.open("1 to 1.avi", CV_FOURCC('M','J','P','G'), 25, cv::Size(width, height)))
{
QMessageBox::warning(0, "保存视频失败", "1 to 1.avi");
return;
}
QString version = "v1.2.0";
QString text = QString("OpenCVDemo %1 QQ21497936 blog.csdn.net/qq21497936").arg(version);
for(;;)
{
cv::Mat frame;
videoCapture >> frame;
if(frame.empty())
{
break;
}
// 沿对角线行列翻转
frame = frame.t();
cv::putText(frame,
cv::String(text.toUtf8().data()),
cv::Point(0, height / 2),
cv::FONT_HERSHEY_SCRIPT_SIMPLEX,
0.8,
cv::Scalar(0,0,255),
3,
8,
false);
cv::imshow("readVideo", frame);
videoWrite << frame;
if(cv::waitKey(1) >= 0)
break;
}
#endif
}
解决方法:使用了中文作为窗口标题要改为英文标题
《OpenCV入门教程》
对应版本号v1.2.0
上一篇:《OpenCV开发笔记(三):OpenCV图像的概念和基本操作》
下一篇:《OpenCV开发笔记(五):OpenCV读取与操作摄像头》
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/100735114