OpenCv图像处理之图像视频摄像头读取与保存

  • 使用cv::imread()读取图片
  • 使用cv::imwrite()存储图片
  • 使用cv::VideoCapture::open()读取视频
  • 使用cv::VideoWriter::write()存储视频
  • 使用cv::VideoCapture读取摄像头
  • 使用互斥量、锁、多线程进行数据读取和显示

使用cv::imread()读取图片

经过上一节的学习,我们了解到opencv处理的图片其实就是对矩阵进行操作,使用cv::imread()对图片进行读取并返回一个矩阵,来看一个例子:

#include <iostream>
#include <opencv2/highgui.hpp>using namespace std;int main() {//imread(const String &filedir,int flags)cv::Mat img = cv::imread("D:/null.jpg", 1);//另一种判空的写法:img.data == NULL;if (img.empty()) {cout << "open the file failed!" << endl;}cv::Mat gray_img = cv::imread("D:/cat.jpg", 0);if (!gray_img.empty()) {cv::imshow("gray_img", gray_img);cv::waitKey(0);}cv::Mat nochange_img = cv::imread("D:/cat.jpg", -1);if (!nochange_img.empty()) {cv::imshow("no_chang", nochange_img);cv::waitKey(0);}return 0;
}

效果显示
open the file failed!

上述代码展示了读取图片的三种不同的状态,这个状态由flags参数决定,flags=1(>0)表示函数需要返回三通道图像,若图片不是三通道则强制转成3通道.flags=0表示函数返回单通道图像,若图片是多通道图片则强制转成单通道.flags=-1(<0)表示不对图像进行通道转换处理.imread()支持图像格式:jpg,jpeg,dib,bmp,png,pbm,ppm,sr,ras,tiff,exr,jp2

使用cv::imwrite()存储图片

上面我们学习了如何读取指定路径下的图片,接下来来看一下如何将处理过的图片进行指定存储.

#include <iostream>
#include <opencv2/highgui.hpp>using namespace std;
using namespace cv;int main() {Mat mat = imread("D:/cat.jpg", 1);if (!mat.empty()) {//Rect(x,y,width,height)Mat roi(mat, Rect(200, 200, 400, 500));//bool imwrite(const String &filedir,InputArray img)//imwrite("D:/cat_roi_write.jpg", roi);//imwrite("D:/cat_roi_write.bmp", roi);bool is_write = imwrite("D:/cat_roi_write.png", roi);cout << "write is succeed?:" << is_write << endl;} else {cerr << "openfile is failed" << endl;}return 0;
}

效果显示
write is succeed?:1

png是无损图片
jpg是压缩成的有损图片
bmp是不压缩的无损图片,大小较大
注意并不是所有Mat对象都能存储为图片,一般来说只有8U类型的单通道和3通道矩阵可以进行图像存储,若需要保存成16U类型的图片,则只能使用png,jpeg 2000,tiff格式进行存储.
为了将其他格式的矩阵保存为图片,opencv提供了Mat::convertTo(),从v::cvtColor()能够将矩阵转换为能够保存的类型格式,若指定目录下已经存在要保存的文件,则会对其进行覆盖.(其中cvtColor()是cv类的成员函数,需要声明头文件#include<opencv2/opencv.hpp>)

使用cv::VideoCapture::open()读取视频

VideoCapture既可以从视频文件读取图像,也可以从摄像头中读取图像.使用VideoCapture::open()打开.

#include <iostream>
#include <opencv2/highgui.hpp>using namespace std;
using namespace cv;int main() {VideoCapture capture;Mat frame;frame = capture.open("D:/test_video.mp4");if (!capture.isOpened()) {cout << "this video can not open" << endl;return -1;} else {cout << "video is successful open=" << capture.isOpened() << endl;}//窗口大小自适应,灵活调整,写在cv::imshow()之前,防止图片尺寸太大imshow显示不全,注意名字和imshow相同,不然可能会显示两个窗口namedWindow("show_frame", WINDOW_AUTOSIZE);while (capture.read(frame)) {imshow("show_frame", frame);//每一帧的等待时间,数字越小读取越快waitKey(1);}//释放视频流,手动调用虚析构函数,open()和VideoCapture的析构函数会自动调用,故可以不手动释放capture.release();return 0;
}

打印是否打开成功的结果:video is successful open=1
调用本地摄像头很容易,将capture.open("D:/test_video.mp4");换成capture.open(0);即可.

使用cv::VideoWriter::write()存储视频

使用opencv存储视频流,需要在初始化时设置一系列参数文件名,编解码器,帧率,宽度,高度等等
CV_FOURCC可以获取的编码格式
CV_FOURCC(‘P’, ‘I’, ‘M’, ‘1’) = MPEG-1 code
CV_FOURCC(‘M’, ‘J’, ‘P’, ‘G’) = motion-jpeg codec
CV_FOURCC(‘M’, ‘P’, ‘4’, ‘2’) = MPEG-4.2 codec
CV_FOURCC(‘D’, ‘I’, ‘V’, ‘3’) = MPEG-4.3 codec
CV_FOURCC(‘D’, ‘I’, ‘V’, ‘X’) = MPEG-4 codec
CV_FOURCC(‘U’, ‘2’, ‘6’, ‘3’) = H263 codec
CV_FOURCC(‘I’, ‘2’, ‘6’, ‘3’) = H263I codec
CV_FOURCC(‘F’, ‘L’, ‘V’, ‘1’) = FLV1 codec

MPEG-1是为CD光盘介质定制的视频和音频压缩格式.
Motion JPEG是一种视频压缩格式,其中每一帧图像都分别使用JPEG编码.
MPEG-4利用很窄的带宽,通过帧重建技术,压缩和传输数据,求出以最少的数据获得最佳的图像质量.

VideoWriter::open()函数原型CV_WRAP virtual bool open(const String& filename, int fourcc, double fps, Size frameSize, bool isColor = true);

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>using namespace std;
using namespace cv;int main() {VideoCapture capture;capture.open("D:/test_video.mp4");if (!capture.isOpened()) {cout << "can not open the video" << endl;}double fps = capture.get(CAP_PROP_FPS);int width = int(capture.get(CAP_PROP_FRAME_WIDTH));int height = int(capture.get(CAP_PROP_FRAME_HEIGHT));int fourcc_type = VideoWriter::fourcc('M', 'P', '4', '2');VideoWriter videoWriter;videoWriter.open("D:/write_video.avi", fourcc_type, fps,Size(width, height), true);if (!videoWriter.isOpened()) {cout << "video_writer can not open" << endl;return -1;}Mat frame;while (capture.read(frame)) {//videoWriter << frame;这种写法也是正确的,使用VideoWriter的输出流进行写入videoWriter.write(frame);}return 0;
}
}

效果显示

使用cv::VideoCapture读取摄像头

#include <iostream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <thread>using namespace std;
using namespace cv;
thread::id main_thread_id = this_thread::get_id();void open_video(VideoCapture &capture_usb, const string &filename, Mat &frame) {capture_usb.open(filename);if (!capture_usb.isOpened()) {cerr << "url not exit" << endl;}if (this_thread::get_id() == main_thread_id) {cout << "this is the main thread" << endl;} else {cout << "this is not the main thread!" << endl;}capture_usb.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G'));capture_usb.set(CAP_PROP_FRAME_HEIGHT, 500);capture_usb.set(CAP_PROP_FRAME_WIDTH, 500);capture_usb.set(CAP_PROP_FPS, 30);namedWindow("capture", WINDOW_AUTOSIZE);while (capture_usb.read(frame)) {imshow("capture", frame);waitKey(1000);}
}void open_video1(VideoCapture &capture_usb, const string &filename, Mat &frame) {capture_usb.open(filename);if (!capture_usb.isOpened()) {cerr << "url not exit" << endl;}if (this_thread::get_id() == main_thread_id) {cout << "this is the main thread" << endl;} else {cout << "this is not the main thread!" << endl;}//设置采集格式capture_usb.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G'));//设置分辨率capture_usb.set(CAP_PROP_FRAME_HEIGHT, 500);capture_usb.set(CAP_PROP_FRAME_WIDTH, 500);//设置每秒读取的图片数量capture_usb.set(CAP_PROP_FPS, 30);namedWindow("capture1", WINDOW_AUTOSIZE);while (capture_usb.read(frame)) {imshow("capture1", frame);waitKey(1000);}
}int main() {VideoCapture capture_usb, local_video_capture, capture_usb1, capture_usb2;Mat frame, frame_video, frame1, frame2;//url为读取的视频流地址(接口)const string filename = url;const string local_file = "D:/test_video.mp4";const string filename1 = url;thread thread_1(open_video, ref(capture_usb), filename, ref(frame));thread thread_2(open_video1, ref(capture_usb1), filename1, ref(frame));thread_2.join();thread_1.detach();for (;;) {if (!capture_usb.isOpened()) {break;}if (!capture_usb1.isOpened()) {break;}capture_usb.release();capture_usb1.release();return 0;
}

capture_usb.set()参数简介

参数 功能
CV_CAP_PROP_POS_MSEC 0 视频文件的当前位置(以毫秒为单位)或视频捕获时间戳
CV_CAP_PROP_POS_FRAMES 1 基于0的索引将被解码/捕获下一帧
CV_CAP_PROP_POS_AVI_RATIO 2 视频文件相对位置:0 - 电影的开始,电影的1 - 结束
CV_CAP_PROP_FRAME_WIDTH 3 视频里每一帧的宽
CV_CAP_PROP_FRAME_HEIGHT 4 视频里每一帧的高
CV_CAP_PROP_FPS 5 视频的帧速
CV_CAP_PROP_FOURCC 6 4个字符表示的视频编码器格式
CV_CAP_PROP_FRAME_COUNT 7 视频的帧数
CV_CAP_PROP_FORMAT 8 byretrieve()返回的Mat对象的格式
CV_CAP_PROP_MODE 9 指示当前捕获模式的后端特定值
CV_CAP_PROP_BRIGHTNESS 10 图像的亮度(仅适用于相机)
CV_CAP_PROP_CONTRAST 11 图像对比度(仅适用于相机)
CV_CAP_PROP_SATURATION 12 图像的饱和度(仅适用于相机)
CV_CAP_PROP_HUE 13 图像的色相(仅适用于相机)
CV_CAP_PROP_GAIN 14 图像的增益(仅适用于相机)
CV_CAP_PROP_EXPOSURE 15 曝光(仅适用于相机)
CV_CAP_PROP_CONVERT_RGB 16 表示图像是否应转换为RGB的布尔标志
CV_CAP_PROP_WHITE_BALANCE 17 目前不支持
CV_CAP_PROP_RECTIFICATION 18 立体摄像机的整流标志(注意:只有当前支持DC1394 v 2.x后端)

使用互斥量、锁、多线程进行数据读取和显示

#include <iostream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <thread>
#include <deque>
#include <mutex>
#include <Windows.h>
#include <ctime>
using namespace std;
using namespace cv;
thread::id main_thread_id = this_thread::get_id();
deque<cv::Mat> mat_deque;
mutex mut;void open_video(VideoCapture &capture_usb, const string &filename, Mat &frame) {capture_usb.open(filename);if (!capture_usb.isOpened()) {cerr << "url not exit" << endl;}if (this_thread::get_id() == main_thread_id) {cout << "this is the main thread" << endl;} else {cout << "this is not the main thread!" << endl;}capture_usb.set(CAP_PROP_FOURCC, VideoWriter::fourcc('M', 'J', 'P', 'G'));capture_usb.set(CAP_PROP_FRAME_HEIGHT, 200);capture_usb.set(CAP_PROP_FRAME_WIDTH, 200);capture_usb.set(CAP_PROP_FPS, 300);capture_usb.set(CAP_PROP_BUFFERSIZE, 3);while (capture_usb.read(frame)) {long start_time = clock();if (waitKey(20) >= 0) { break; }//创建线程锁锁住互斥量lock_guard<mutex> lk(mut);mat_deque.push_back(frame);long end_time = clock();cout<<"read_total_time="<<end_time-start_time<<endl;}
}void get_video_data(Mat &frame) {while (true) {if (!mat_deque.empty()) {long start_time = clock();unique_lock<mutex> lk(mut);frame = mat_deque.back();long end_time = clock();cout<<"get_total_time="<<end_time-start_time<<endl;//拿到数据之后解锁lk.unlock();if (waitKey(20) >= 0) { break; }imshow("capture", frame);waitKey(1000);mat_deque.pop_back();}}
}int main() {VideoCapture capture_usb;Mat frame, frame_video, frame1, frame2;const string filename = url;const string filename1 = url;const string filename_123 = url;thread thread_1(open_video, ref(capture_usb), filename_123, ref(frame));thread thread3(get_video_data,ref(frame_video));thread_1.join();thread3.join();for (int i = 0; i < 5; ++i) {thisthread::sleepfor(2000ms);}return 0;
}

OpenCv图像处理之图像视频摄像头读取和保存相关推荐

  1. Java OpenCV 图像处理32.4 视频分析和对象跟踪 切换背景

    Java OpenCV 图像处理32.4 视频分析和对象跟踪 切换背景 方法 含义 解释 bitwise_and "与"操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制 ...

  2. 《OpenCv视觉之眼》Python图像处理二十一:Opencv图像处理之图像线性变换和非线性变换的方法及原理

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  3. OpenCV图像处理(十一)---图像梯度

    安培定则:也叫右手螺旋定则,是表示电流和电流激发磁场的磁感线方向间关系的定则.通电直导线中的安培定则(安培定则一):用右手握住通电直导线,让大拇指指向电流的方向,那么四指指向就是磁感线的环绕方向:通电 ...

  4. OpenCv图像处理之图像归一化

    OpenCv图像处理之图像归一化 归一化 中心化 标准化 归一化 图像处理中,图像单通道像素值为0~255之间的uchar类型,通常使用min-max归一化将其转化为0~1区间之间,既不会改变数据的分 ...

  5. Python OpenCV 视频的读取和保存

    1. 打开本地的摄像头,读取视频的每一帧 import cv2 # 1: connect camera via USB , 0: connect camera installed in your co ...

  6. python使用opencv保存视频_Pythone OpenCV学习笔记之:视频文件读取与保存

    # -*- coding: utf-8 -*- # 读取和保存视频 import cv2 as cv import numpy as np def decode_fourcc(v): v = int( ...

  7. opencv图像处理时使用stringstream批量读取图片,处理后并保存

    简介: 同文件输入输出流一样,使用stringstream可以批量读取图片,处理后并进行保存.因为C++中头文件 stringstream既可以从string读数据也可向string写数据,利于其这个 ...

  8. python保存代码_python如何实现视频的读取与保存功能(代码实例)

    本篇文章给大家带来的内容是介绍python如何实现视频读取与保存功能.有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所助. 1.打开摄像头 #打开摄像头 import cv2 cap = c ...

  9. python opencv —— io(帧、图像、视频的读取与保存)

    0. VideoCapture VideoCapture:构造函数: 常见成员函数: open:打开视频文件,或者捕获视频设备,该函数会首先调用 release() 函数以关闭已打开的文件或设备: P ...

最新文章

  1. 如何用 OS X 的 Xcode 写C语言程序
  2. python的TCP编程
  3. C#计算两个日期的相隔天数
  4. [Warning] TIMESTAMP with implicit DEFAULT value is
  5. Java面向对象(五)abstract --- 抽象
  6. Catalog Service - 解析微软微服务架构eShopOnContainers(三)
  7. java不适合开发cv吗_JavaCV开发环境的配置
  8. C#操作Cookie
  9. apk android lite,APKPure Lite
  10. Linux ping ipv66,IPV6的测试-ipv6网卡配置-ipv6的nginx配置-ipv6的ping测试-ipv6的curl测试...
  11. ERP流程的一个生动的示例~~
  12. jupyter notebook 中添加 Julia kernel
  13. Ubuntu14.04下安装Samba
  14. SylixOS armv8 任务切换
  15. UCOII信号量与消息邮箱
  16. 《遥感原理与应用》孙家抦版知识点总结(含简答题)——第三章
  17. 国家代号(CountryCode) - 常用国家地区代码和国际电话代码
  18. 苹果授权登录,后端校验(Sign in with Apple)
  19. iphone申请AppleID后无法登陆App Store
  20. 垃圾短信相关用户细分方案

热门文章

  1. 谷歌又发新操作系统了!
  2. python七巧板三角形_canvas基础入门(二)绘制线条、三角形、七巧板
  3. 某项目GSM的tuner配置
  4. chrome无法打开无痕模式的解决方案
  5. MySQL连接查询,子查询,union(合并),分页
  6. 微型计算机硬件系统中PROM是,1微型计算机硬件系统中最核心的部件是CPU.doc
  7. 数据挖掘和大数据分析
  8. 随机事件及其概率运算
  9. python 将输出打印到文件
  10. GD32F4xx控制DGUS触控按键