原文:https://courses.learnopencv.com/courses/227056/lectures/3541926
代码:https://courses.learnopencv.com/courses/227056/lectures/3804002
对原文进行了不全面的重点笔记摘录
OpenCV基础-2
在图片上作画
能够画如下的形状或文字
- Line
- Circle
- Ellipse
- Rectangle
- Text
下面是伪代码
cv::line ( image, starting point , end point , color , line thickness, line type)
cv:: circle ( image, center, radius, color of border, line thickness / fill type, line type)
cv:: ellipse ( image, center, axes lengths, rotation degree of ellipse, starting angle , ending angle, color, line thickness / fill type, line type)
cv:: rectangle ( image, upper left corner vertex, lower right corner vertex, line thickness / fill type, line type)
cv :: putText ( image, text, starting point of text, font type, font scale, color, linetype )
linetype 参数用来控制渲染质量,比如设置为CV_AA,(anti-alias),就可以画出消除锯齿的线
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
int main(void) {
Mat image = imread("mark.jpg");
// Draw a line
// We are making a copy of image because we don't want to draw all the shapes on one image
Mat imageLine = image.clone();
line(imageLine, Point(322, 179), Point(400, 183), Scalar(0, 255, 0), 1, CV_AA);
imshow("line", imageLine);
imwrite("imageLine.jpg", imageLine)
waitKey(0);
return 0;
}
处理鼠标事件
我们能够使用OpenCV检测诸如左键、右键或者鼠标在窗口上的位置等鼠标事件。为了达到目的,我们需要创建一个命名窗口并且为它指定一个回调函数,我们将在下面的代码中展示。
选择圆心并拖动半径,按c清除图像,ESC退出
C++ [ HighGui - Mouse ] [ highguiMouse.cpp ]
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
/*This program shows how highgui enables us to take mouse inputs.
In this code we use mouse input to draw a circle on an image.
The mouse is dragged from the center to one of the points on the
circumference. ‘c’ can be pressed to remove the drawn circles. */
// Points to store the center of the circle and a point on the
circumference
Point center, circumference;
// Source image
Mat source;
/*drawCircle the callback function is called when there is a mouse event
like left click ( indicated by EVENT_LBUTTONDOWN ). The coordinates
relative to the namedWindow is captured by this function in the
variables (x,y). The function records the points of the circle’s center
and a point on the circumference, hence allowing us to draw the desired
circle on the image.*/
// function which will be called on mouse input
void drawCircle(int action, int x, int y, int flags, void *userdata)
{
// Action to be taken when left mouse button is pressed
if( action == EVENT_LBUTTONDOWN )
{
center = Point(x,y);
// Mark the center
circle(source, center, 1, Scalar(255,255,0), 2, CV_AA );
}
// Action to be taken when left mouse button is released
else if( action == EVENT_LBUTTONUP)
{
circumference = Point(x,y);
// Calculate radius of the circle
float radius = sqrt(pow(center.x-circumference.x,2)+
pow(center.y-circumference.y,2));
// Draw the circle
circle(source, center, radius, Scalar(0,255,0), 2, CV_AA );
imshow("Window", source);
}
}
int main()
{
source = imread("boy.jpg",1);
// Make a dummy image, will be useful to clear the drawing
Mat dummy = source.clone();
namedWindow("Window");
// highgui function called when mouse events occur
setMouseCallback("Window", drawCircle);
int k=0;
// loop until escape character is pressed
while(k!=27)
{
imshow("Window", source );
putText(source,"Choose center, and drag, Press ESC to exit and c to clear" ,Point(10,30), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(255,255,255), 2 );d
k= waitKey(20) & 0xFF;
if(k== 99)
// Another way of cloning
dummy.copyTo(source);
}
return 0;
}
读写、显示视频
这一节讲述OpenCV中对视频的操作。
一个视频其实就是一段快速切换的图片,其中明显的问题就是图片切换移动得多快?我们用帧每秒(fps)来衡量这样的速度。一般来说25帧每秒,是人肉眼能够分辨的极限。
OpenCV为我们提供了方便的操作接口。
1. 读取视频
第一步我们需要创建一个VideoCapture对象,它的参数可以是WebCam摄像头的设备编号或者是视频文件名。
当只有一个摄像头时,使用参数‘0’来使用唯一的那个摄像头,有多个摄像头时,可以使用编号1,2等来使用不同的设备。
VideoCapture cap("chaplin.mp4");
2. 显示视频
读取了视频之后,我们可以一帧一帧的来展示视频。我们可以利用显示图片的方法来显示我们视频的一帧,我们使用imshow()函数。
在显示图片的情况下,我们在imshow()之后使用waitKey(num)来暂停,参数为‘0’。在视频中,通常使用比num>0大的数,来延迟num毫秒。
在使用webcam的时候,使用waitKey(1)是合适的,因为显示的帧速率会被webcam所限制。
在从视频文件中读取时,使用waitKey(1)可能也是合适的,因为这样可以延迟一秒来使得线程空出来进行我们想要的处理。
在极少的情况下我们要回放视频会设置特定的帧速率。
C++ [ Reading a video file ] [ videoRead.cpp ]
//In the following code, we will use the VideoCapture Object to
//read a video file and display it.
//Include opencv header files
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(){
//In this block,we create a video capture object and
//read a input video file.
// Create a VideoCapture object and open the input file
// If the input is the web camera, pass 0 instead of the video file name
VideoCapture cap("chaplin.mp4");
// Check if camera opened successfully and read a frame from the object cap
if(!cap.isOpened()){
cout << "Error opening video stream or file" << endl;
return -1;
}
//Read and display video frames until video is completed or
//user quits by pressing ESC
while(1){
Mat frame;
// Capture frame-by-frame
cap >> frame;
// If the frame is empty, break immediately
if (frame.empty())
break;
// Display the resulting frame
imshow( "Frame", frame );
// Press ESC on keyboard to exit
char c=(char)waitKey(25);
if(c==27)
break;
}
// When everything done, release the video capture object
cap.release();
// Closes all the frames
destroyAllWindows();
return 0;
}
3. 写视频
当完成对视频的处理后,需要把视频存储起来。
对图片的存储,可以使用cv2.imwrite()。
对视频的处理,我们需要先创建一个VideoWriter 对象,然后指定1. 带有格式的名字; 2. FourCC编码,3. FPS(帧每秒)4. 帧大小
// Define the codec and create VideoWriter object.The output is stored in 'outcpp.avi' file.
// Define the fps to be equal to 10. Also frame size is passed.
VideoWriter video("outcpp.avi",CV_FOURCC('M','J','P','G'),10, Size(frame_width,frame_height));
C++ [ Writing to a video file ] [ videoWrite.cpp ]
// Include opencv header files
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
/*
In the following code, we will use the VideoCapture Object to read a video
from the webcam, display the feed from webcam and save it by using a
VideoWriter Object.
*/
int main(){
// Create a VideoCapture object and open the input file
// If the input is the web camera, pass 0 instead of the video file name
VideoCapture cap(0);
// Check if camera opened successfully
if(!cap.isOpened()){
cout << "Error opening video stream or file" << endl;
return -1;
}
//In this block of code, we obtain the system dependent
//frame width and height.
// Default resolutions of the frame are obtained.
// The default resolutions are system dependent.
int frame_width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
//We create the videoWriter object ‘video’, name the output file as
//‘outcpp.avi’ and define the 4 FOURCC code. We also specify the ‘fps’
//value and the dimensions of the system dependent frame.
// Define the codec and create VideoWriter object.The output is stored
// in 'outcpp.avi' file.
VideoWriter video("outcpp.avi",CV_FOURCC('M','J','P','G'),10, Size(frame_width,frame_height));
//Read and save the feed from webcam until ESC is pressed .
while(1){
Mat frame;
// Capture frame-by-frame
cap >> frame;
// If the frame is empty, break immediately
if (frame.empty())
break;
// Write the frame into the file 'outcpp.avi'
video.write(frame);
// Display the resulting frame
imshow( "Frame", frame );
// Press ESC on keyboard to exit
char c=(char)waitKey(25);
if(c==27)
break;
}
// When everything done, release the video capture object
cap.release();
video.release();
// Closes all the frames
destroyAllWindows();
return 0;
}