第二十九周学习笔记

第二十九周学习笔记

本周主要学习opencv的一些内容
代码在这

图片读取和显示

图片以矩阵形式存储在cv::Mat中,cv::Mat会根据图片自动分配内存,同时也会自动释放内存

函数和参数

  • cv::imread("path_to_img"),读取图片,返回cv::Mat
  • cv::Mat.empty(),判断图片是否读取成功,失败则返回true
  • cv::namedWindow("name_of_window"),用来显示图片的窗口
  • cv::imshow("name_of_window",img),将图片img显示在对应窗口上
  • cv::waitKey(0)暂停程序,防止程序结束后图片窗口自动销毁
  • cv::destroyWindow("name_of_window"),手动销毁窗口

示例

#include <opencv2/highgui/highgui.hpp>
int main() {
  cv::Mat img = cv::imread("1.jpg");
  if (img.empty())
    return -1;
  cv::namedWindow("Window");
  cv::imshow("Window", img);
  cv::waitKey(0);
  cv::destroyWindow("Window");
  return 0;
}

编译命令

g++ -o main Ex2_1Display.cpp -lopencv_core -lopencv_highgui -lopencv_imgcodecs

视频读取和显示

OpenCV中,视频的显示是通过连续的图片显示实现的,OpenCV先使用cv::VideoCapture读取视频文件,然后将视频的每一帧输入到cv::Mat中,再连续地显示这些图像,从而实现视频播放

函数和参数

  • cv::VideoCapture.open("path_to_video"),读取视频文件
  • cv::VideoCapture >> frame,输入下一帧到frame

示例

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

int main() {
  cv::namedWindow("Window1", cv::WINDOW_AUTOSIZE);
  cv::VideoCapture cap;
  cap.open("1.mp4");
  cv::Mat frame;
  for (;;) {
    cap >> frame;
    if (frame.empty())
      break;
    cv::imshow("Window1", frame);
    if (cv::waitKey(33) >= 0) // 这个数字控制了视频的播放速度,也就是两帧之间的间隔,按任意键结束播放
      break;
  }
}

编译

g++ Ex2_3Video.cpp -o main -lopencv_core -lopencv_highgui -lopencv_imgcodecs -lopencv_videoio -lopencv_video -lopencv_videostab -lopencv_imgproc

视频进度跳转

可以在视频上加一条进度条实现播放进度的控制

函数和参数

  • cv::createTrackbar("name_of_trackbar", "name_of_window", slider_position, max_value, onTrackbarSlide)五个参数分别为,trackbar名,窗口名,滑块初始位置,最大值,滑动时的响应函数
  • cv::VideoCapture.set(cv::CAP_PROP_POS_FRAMES, pos),设置下一帧读取的位置

示例

#include <opencv4/opencv2/highgui/highgui.hpp>
#include <opencv4/opencv2/imgproc/imgproc.hpp>

using namespace std;

cv::VideoCapture g_cap;

void onTrackbarSlide(int pos, void *) {
  g_cap.set(cv::CAP_PROP_POS_FRAMES, pos); //????
}

int main() {
  cv::namedWindow("Window1", cv::WINDOW_AUTOSIZE);
  g_cap.open("1.mp4");
  int frames = (int)g_cap.get(cv::CAP_PROP_FRAME_COUNT);
  cv::createTrackbar("Position", "Window1", 0, frames, onTrackbarSlide);
  cv::Mat frame;
  for (;;) {
    g_cap >> frame;
    if (frame.empty())
      break;
    int current_pos = (int)g_cap.get(cv::CAP_PROP_POS_FRAMES);
    cv::setTrackbarPos("Position", "Window1",
                       current_pos); // 保证进度条的位置和播放进度一致
    cv::imshow("Window1", frame);
    if (cv::waitKey(33) > 0) {
      break;
    }
  }
  return (0);
}

图像变换

  • 高斯模糊cv::GaussianBlur(image, out, cv::Size(5, 5), 3, 3);
  • 下采样cv::pyrDown(in, out);
  • BGR2GRAYcv::cvtColor(img_rgb, img_gry, cv::COLOR_BGR2GRAY);
  • Canny边缘提取cv::Canny(img_gry, img_cny, 10, 100, 3, true);

像素取值和赋值

示例

#include <iostream>
#include <opencv2/opencv.hpp>

int main() {
  cv::Mat img = cv::imread("1.jpg");
  int x = 16;
  int y = 32;

  cv::Vec3b intensity = img.at<cv::Vec3b>(y, x);

  uchar blue = intensity[0];
  uchar green = intensity[1];
  uchar red = intensity[2];

  std::cout << "----------Before----------" << std::endl;
  std::cout << "At (x, y) = (" << x << ", " << y << "): (blue, green, red) = ("
            << (unsigned int)blue << ", " << (unsigned int)green << ", "
            << (unsigned int)red << ")" << std::endl;

  img.at<cv::Vec3b>(y, x) = {0, 0, 0};

  cv::Vec3b intensity2 = img.at<cv::Vec3b>(y, x);

  uchar blue2 = intensity2[0];
  uchar green2 = intensity2[1];
  uchar red2 = intensity2[2];

  std::cout << "----------After----------" << std::endl;
  std::cout << "At (x, y) = (" << x << ", " << y << "): (blue, green, red) = ("
            << (unsigned int)blue2 << ", " << (unsigned int)green2 << ", "
            << (unsigned int)red2 << ")" << std::endl;
}

输出视频

与读取视频恰相反的过程

函数和参数

  • cv::VideoWriter.open(1,2,3,4)打开一个空的视频,四个参数分别为,文件名,视频编解码器,fps,每帧的Size

示例

#include <opencv4/opencv2/opencv.hpp>

int main() {
  cv::VideoCapture cap("1.mp4");
  cv::VideoWriter writer;
  cv::Size size(cap.get(cv::CAP_PROP_FRAME_WIDTH),
                cap.get(cv::CAP_PROP_FRAME_HEIGHT));
  writer.open("out.mp4", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'),
              cap.get(cv::CAP_PROP_FPS), size);
  cv::Mat frame;

  for(;;){
    cap >> frame;
    if(frame.empty())break;
    writer << frame;
  }
  writer.release();
}

cv::waitKey的用法小结

cv::waitKey(int num)

cv::waitKey暂时中断程序

  • num小于等于0,等待键入后程序继续
  • num大于0,等待键入或者num毫秒后程序继续

场景1:显示图片

#include <opencv2/highgui/highgui.hpp>
int main() {
  cv::Mat img = cv::imread("1.jpg");
  if (img.empty())
    return -1;
  cv::namedWindow("Window");
  cv::imshow("Window", img);
  cv::waitKey(0); // 在此停下,防止程序直接结束,显示图片的窗口自动关闭
  cv::destroyWindow("Window");
  return 0;
}

场景2:控制视频播放时间

在播放视频时,cv::waitKey的参数控制了两帧之间的播放间隔(毫秒),可以通过计算得到每帧占多少毫秒来实现视频的原速播放

#include <iostream>
#include <opencv4/opencv2/opencv.hpp>
using namespace std;
int main() {
  cv::VideoCapture cap("1.mp4");
  cv::Mat frame;

  cv::namedWindow("Window1");

  double fps = cap.get(cv::CAP_PROP_FPS);
  cout << fps;
  for (;;) {
    cap >> frame;
    if (frame.empty())
      break;
    cv::imshow("Window1", frame);
    if (cv::waitKey(1000/fps) >= 0) { // 等待的时间即是两帧之间的间隔
      break;
    }
  }
}

场景3:等待键入,并执行相应操作

...
char c = (char)cv::waitKey(10); // 好像不写(char)也行
    if (c == 's') {
      cout << "input s" << endl;
    }
    if (c == 'r') {
      cout << "input r" << endl;
    }
    if (c == 27) { // Esc
	  cout << "input esc" << endl; 
	}    
...

一些属性

cv::VideoCapture cap("1.mp4");
int frames = (int)g_cap.get(cv::CAP_PROP_FRAME_COUNT); \\ 帧数
int tmpw = (int)g_cap.get(cv::CAP_PROP_FRAME_WIDTH); \\ 宽
int tmph = (int)g_cap.get(cv::CAP_PROP_FRAME_HEIGHT); \\ 高
double fps = cap.get(cv::CAP_PROP_FPS); \\ fps

注意事项

  • opencv代码的编译样例
g++ Ex2_1Display.cpp -o main -lopencv_core -lopencv_highgui -lopencv_imgcodecs -lopencv_videoio -lopencv_video -lopencv_videostab -lopencv_imgproc
  • fps用double类型读取
cv::VideoCapture cap("1.mp4");
double fps = cap.get(cv::CAP_PROP_FPS);
  • 建议手动输入命名空间cv::
  • 头文件opencv2/opencv.hpp可以导入所有的OpenCV模块,也可以仅仅导入需要的模块来减少编译的时间
  • 在大的程序中,需要手动调用cv::destroyWindow(Windowname),防止内存泄露
  • 程序中图片的相对目录使用的是相对编译位置的相对目录
  • namedWindow的默认size=cv::WINDOW_AUTOSIZE

下周目标

同时学习opencv和CS231n,并完成上周报告中问题的回答和额外资料的阅读

猜你喜欢

转载自blog.csdn.net/luo3300612/article/details/87884525