OpenCV实例精解(OpenCV By Example)

第二章 OpenCV基础知识
2.6读写图像

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

int main(int argc, const char** argv)
{
	// Read images
	Mat color = imread("lena.jpg");
	Mat gray = imread("lena.jpg", 0);

	// Write images
	imwrite("lenaGray.jpg", gray);

	// Get same pixel with opencv function
	int myRow = color.cols - 1;
	int myCol = color.rows - 1;
	Vec3b pixel = color.at<Vec3b>(myRow, myCol); //cv::Mat::at<typename>(row,col)
	cout << "Pixel value (B,G,R): (" << (int)pixel[0] << "," << (int)pixel[1] << "," << (int)pixel[2] << ")" << endl;

	// show images
	imshow("Lena BGR", color);
	imshow("Lena Gray", gray);
	// wait for any key press
	waitKey(0);
	return 0;
}

2.7读取视频和摄像头

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

// OpenCV command line parser functions
// Keys accecpted by command line parser
const char* keys =
{
	"{help h usage ? | | print this message}"
	"{@video | | Video file, if not defined try to use webcamera}"
};

int main(int argc, const char** argv)
{
	CommandLineParser parser(argc, argv, keys);
	parser.about("Chapter 2. v1.0.0");
	//If requires help show
	if (parser.has("help"))
	{
		parser.printMessage();
		return 0;
	}

	String videoFile = parser.get<String>(0);

	// Check if params are correctly parsed in his variables
	if (!parser.check())
	{
		parser.printErrors();
		return 0;
	}

	VideoCapture cap; // open the default camera
	if (videoFile != "")
		cap.open(videoFile);
	else
		cap.open(0);
	if (!cap.isOpened())  // check if we succeeded
		return -1;

	namedWindow("Video", 1);
	for (;;)
	{
		Mat frame;
		cap >> frame; // get a new frame from camera
		imshow("Video", frame);
		if (waitKey(30) >= 0) break;
	}
	// Release the camera or video cap
	cap.release();

	return 0;
}

2.9矩阵基本运算

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

// OpenCV includes
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

// OpenCV command line parser functions
// Keys accecpted by command line parser
const char* keys =
{
	"{help h usage ? | | print this message}"
	"{@sample |0 | Sample number to show}"
};


int main(int argc, const char** argv)
{
	CommandLineParser parser(argc, argv, keys);
	parser.about("Chapter 2. v1.0.0");
	//If requires help show
	if (parser.has("help"))
	{
		parser.printMessage();
		return 0;
	}

	int sample = parser.get<int>(0);

	// Check if params are correctly parsed in his variables
	if (!parser.check())
	{
		parser.printErrors();
		return 0;
	}

	switch (sample)
	{
	case 0:
	{	cout << "Sample 0, Mat zeros" << endl;
	Mat m = Mat::zeros(5, 5, CV_32F);
	cout << m << endl;
	break;
	}
	case 1:
	{	cout << "Sample 0, Mat ones" << endl;
	Mat m = Mat::ones(5, 5, CV_32F);
	cout << m << endl;
	break;
	}
	case 2:
	{	cout << "Sample 0, Mat eye" << endl;
	Mat m = Mat::eye(5, 5, CV_32F);
	cout << m << endl;

	Mat a = Mat::eye(Size(3, 2), CV_32F);
	Mat b = Mat::ones(Size(3, 2), CV_32F);
	Mat c = a + b;
	Mat d = a - b;
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << d << endl;
	break;
	}
	case 3:
	{	cout << "Sample 0, Mat operations:" << endl;
	Mat m0 = Mat::eye(3, 3, CV_32F);
	m0 = m0 + Mat::ones(3, 3, CV_32F);
	Mat m1 = Mat::eye(2, 3, CV_32F);
	Mat m2 = Mat::ones(3, 2, CV_32F);

	cout << "\nm0\n" << m0 << endl;
	cout << "\nm1\n" << m1 << endl;
	cout << "\nm2\n" << m2 << endl;

	cout << "\nm1.*2\n" << m1 * 2 << endl;
	cout << "\n(m1+2).*(m1+3)\n" << (m1 + 1).mul(m1 + 3) << endl;
	cout << "\nm1*m2\n" << m1*m2 << endl;
	cout << "\nt(m2)\n" << m2.t() << endl;
	cout << "\ninv(m0)\n" << m0.inv() << endl;
	break;
	}
	case 4:
	{
			  Mat image = imread("lena.jpg", 0);
			  int myRow = 511;
			  int myCol = 511;
			  int val = *(image.data + myRow*image.cols*image.channels() + myCol);
			  cout << "Pixel value: " << val << endl;
			  imshow("Lena", image);
			  waitKey(0);
			  break;
	}
	case 5:
	{
			  Mat image = imread("lena.jpg");
			  int myRow = 511;
			  int myCol = 511;
			  int B = *(image.data + myRow*image.cols*image.channels() + myCol + 0);
			  int G = *(image.data + myRow*image.cols*image.channels() + myCol + 1);
			  int R = *(image.data + myRow*image.cols*image.channels() + myCol + 2);
			  cout << "Pixel value (B,G,R): (" << B << "," << G << "," << R << ")" << endl;
			  imshow("Lena", image);
			  waitKey(0);
			  break;
	}
	case 6:
	{
			  Vec<double, 19> myVector;
			  for (int i = 0; i<19; i++){
				  myVector[i] = i;
			  }
			  cout << myVector << endl;

	}
	}

	return 0;

}

2.10文件存储写入

#include "opencv2/opencv.hpp"
using namespace cv;

int main(int, char** argv)
{
	// create our writter
	FileStorage fs("test.txt", FileStorage::WRITE);
	// Save an int
	int fps = 5;
	fs << "fps" << fps;
	// Create some mat sample
	Mat m1 = Mat::eye(2, 3, CV_32F);
	Mat m2 = Mat::ones(3, 2, CV_32F);
	Mat result = (m1 + 1).mul(m1 + 3);
	// write the result
	fs << "Result" << result;
	// release the file
	fs.release();

	FileStorage fs2("test.txt", FileStorage::READ);

	Mat r;
	fs2["Result"] >> r;
	std::cout << r << std::endl;

	fs2.release();

	return 0;
}

第三章 图形用户界面和基本滤波
3.2基本图形用户界面

#include <iostream>
#include <string>
#include <sstream>
using namespace std;
// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

int main(int argc, const char** argv)
{
	// Read images
	Mat lena = imread("lena.jpg");
	Mat photo = imread("photo.jpg");

	// Create windows
	namedWindow("Lena", WINDOW_NORMAL);
	namedWindow("Photo", WINDOW_AUTOSIZE);

	// Move window
	moveWindow("Lena", 10, 10);
	moveWindow("Photo", 520, 10);

	// show images
	imshow("Lena", lena);
	imshow("Photo", photo);

	// Resize window, only non autosize
	resizeWindow("Lena", 512, 512);

	// wait for any key press
	waitKey(0);

	// Destroy the windows
	destroyWindow("Lena");
	destroyWindow("Photo");

	// Create 10 windows
	for (int i = 0; i< 10; i++)
	{
		ostringstream ss;
		ss << "Photo " << i;
		namedWindow(ss.str());
		moveWindow(ss.str(), 20 * i, 20 * i);
		imshow(ss.str(), photo);
	}

	waitKey(0);
	// Destroy all windows
	destroyAllWindows();
	return 0;
}

3.4在界面添加滑动条和鼠标事件

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

// Create a variable to save the position value in track
int blurAmount = 20;

// Trackbar call back function
static void onChange(int pos, void* userInput);

//Mouse callback
static void onMouse(int event, int x, int y, int, void* userInput);

int main(int argc, const char** argv)
{
	// Read images
	Mat lena = imread("lena.jpg");

	// Create windows
	namedWindow("Lena");

	// create a trackbark
	createTrackbar("Lena", "Lena", &blurAmount, 30, onChange, &lena);

	setMouseCallback("Lena", onMouse, &lena);

	// Call to onChange to init
	onChange(blurAmount, &lena);

	// wait app for a key to exit
	waitKey(0);

	// Destroy the windows
	destroyWindow("Lena");

	return 0;
}

// Trackbar call back function
static void onChange(int pos, void* userInput)
{
	if (pos <= 0)
		return;
	// Aux variable for result
	Mat imgBlur;

	// Get the pointer input image
	Mat* img = (Mat*)userInput;

	// Apply a blur filter
	blur(*img, imgBlur, Size(pos, pos));

	// Show the result
	imshow("Lena", imgBlur);
}

//Mouse callback
static void onMouse(int event, int x, int y, int, void* userInput)
{
	if (event != EVENT_LBUTTONDOWN)
		return;

	// Get the pointer input image
	Mat* img = (Mat*)userInput;

	// Draw circle
	circle(*img, Point(x, y), 10, Scalar(0, 255, 0), 3);

	// Call on change to get blurred image
	onChange(blurAmount, img);

}

3.5在界面添加按钮(使用QT)

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

Mat img;
bool applyGray = false;
bool applyBlur = false;
bool applySobel = false;

void applyFilters(){
	Mat result;
	img.copyTo(result);
	if (applyGray){
		cvtColor(result, result, COLOR_BGR2GRAY);
	}
	if (applyBlur){
		blur(result, result, Size(5, 5));
	}
	if (applySobel){
		Sobel(result, result, CV_8U, 1, 1);
	}
	imshow("Lena", result);
}

void grayCallback(int state, void* userData)
{
	applyGray = true;
	applyFilters();
}
void bgrCallback(int state, void* userData)
{
	applyGray = false;
	applyFilters();
}

void blurCallback(int state, void* userData)
{
	applyBlur = (bool)state;
	applyFilters();
}

void sobelCallback(int state, void* userData)
{
	applySobel = !applySobel;
	applyFilters();
}

int main(int argc, const char** argv)
{
	// Read images
	img = imread("lena.jpg");

	// Create windows
	namedWindow("Lena");

	// create Buttons
	createButton("Blur", blurCallback, NULL, QT_CHECKBOX, 0);

	createButton("Gray", grayCallback, NULL, QT_RADIOBOX, 0);
	createButton("RGB", bgrCallback, NULL, QT_RADIOBOX, 1);

	createButton("Sobel", sobelCallback, NULL, QT_PUSH_BUTTON, 0);

	// wait app for a key to exit
	waitKey(0);

	// Destroy the windows
	destroyWindow("Lena");

	return 0;
}

3.6支持OpenGL

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

// OpenGL includes
#ifdef __APPLE__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

// OpenCV includes
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;

Mat frame;
GLfloat angle= 0.0;
GLuint texture; 
VideoCapture camera;

int loadTexture() {

    if (frame.data==NULL) return -1;
   
    glBindTexture( GL_TEXTURE_2D, texture ); //bind the texture to it's array
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, frame.cols, frame.rows,0, GL_BGR, GL_UNSIGNED_BYTE, frame.data);
    return 0;

}

void on_opengl(void* param)
{
    glLoadIdentity();  
    // Load Texture
    glBindTexture( GL_TEXTURE_2D, texture ); 
    // Rotate plane
    glRotatef( angle, 1.0f, 1.0f, 1.0f );
    // Create the plate
    glBegin (GL_QUADS);
    glTexCoord2d(0.0,0.0); glVertex2d(-1.0,-1.0); 
    glTexCoord2d(1.0,0.0); glVertex2d(+1.0,-1.0); 
    glTexCoord2d(1.0,1.0); glVertex2d(+1.0,+1.0);
    glTexCoord2d(0.0,1.0); glVertex2d(-1.0,+1.0);
    glEnd();

}

int main( int argc, const char** argv )
{
    // Open WebCam
    camera.open(0);
    if(!camera.isOpened())
        return -1;

    // Create new windows
    namedWindow("OpenGL Camera");
    
    // Enable texture
    glEnable( GL_TEXTURE_2D );  
    glGenTextures(1, &texture);
    
    setOpenGlDrawCallback("OpenGL Camera", on_opengl);

    while(waitKey(30)!='q'){
        camera >> frame;
        // Create first texture
        loadTexture();
        updateWindow("OpenGL Camera");
        angle =angle+4;
    }
    
	
	// Destroy the windows
	destroyWindow("OpenGL Camera");
	
	return 0;
}

第四章 直方图和滤波器

#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
using namespace std;

// OpenCV includes
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
Mat img;

// OpenCV command line parser functions
// Keys accecpted by command line parser
const char* keys =
{
	"{help h usage ? | | print this message}"
	"{@image | | Image to process}"
};

void showHistoCallback(int state, void* userData)
{
	// Separate image in BRG
	vector<Mat> bgr;
	split(img, bgr);

	// Create the histogram for 256 bins
	// The number of possibles values
	int numbins = 256;

	/// Set the ranges ( for B,G,R) )
	float range[] = { 0, 256 };
	const float* histRange = { range };

	Mat b_hist, g_hist, r_hist;

	calcHist(&bgr[0], 1, 0, Mat(), b_hist, 1, &numbins, &histRange);
	calcHist(&bgr[1], 1, 0, Mat(), g_hist, 1, &numbins, &histRange);
	calcHist(&bgr[2], 1, 0, Mat(), r_hist, 1, &numbins, &histRange);

	// Draw the histogram
	// We go to draw lines for each channel
	int width = 512;
	int height = 300;
	// Create image with gray base
	Mat histImage(height, width, CV_8UC3, Scalar(20, 20, 20));

	// Normalize the histograms to height of image
	normalize(b_hist, b_hist, 0, height, NORM_MINMAX);
	normalize(g_hist, g_hist, 0, height, NORM_MINMAX);
	normalize(r_hist, r_hist, 0, height, NORM_MINMAX);

	int binStep = cvRound((float)width / (float)numbins);
	for (int i = 1; i< numbins; i++)
	{
		line(histImage,
			Point(binStep*(i - 1), height - cvRound(b_hist.at<float>(i - 1))),
			Point(binStep*(i), height - cvRound(b_hist.at<float>(i))),
			Scalar(255, 0, 0)
			);
		line(histImage,
			Point(binStep*(i - 1), height - cvRound(g_hist.at<float>(i - 1))),
			Point(binStep*(i), height - cvRound(g_hist.at<float>(i))),
			Scalar(0, 255, 0)
			);
		line(histImage,
			Point(binStep*(i - 1), height - cvRound(r_hist.at<float>(i - 1))),
			Point(binStep*(i), height - cvRound(r_hist.at<float>(i))),
			Scalar(0, 0, 255)
			);
	}

	imshow("Histogram", histImage);

}

void equalizeCallback(int state, void* userData)
{
	Mat result;
	// Convert BGR image to YCbCr
	Mat ycrcb;
	cvtColor(img, ycrcb, COLOR_BGR2YCrCb);

	// Split image into channels
	vector<Mat> channels;
	split(ycrcb, channels);

	// Equalize the Y channel only
	equalizeHist(channels[0], channels[0]);

	// Merge the result channels
	merge(channels, ycrcb);

	// Convert color ycrcb to BGR
	cvtColor(ycrcb, result, COLOR_YCrCb2BGR);

	// Show image
	imshow("Equalized", result);
}

void lomoCallback(int state, void* userData)
{
	Mat result;

	const double E = std::exp(1.0);
	// Create Lookup table for color curve effect
	Mat lut(1, 256, CV_8UC1);
	for (int i = 0; i<256; i++)
	{
		float x = (float)i / 256.0;
		lut.at<uchar>(i) = cvRound(256 * (1 / (1 + pow(E, -((x - 0.5) / 0.1)))));
	}

	// Split the image channels and apply curve transform only to red channel
	vector<Mat> bgr;
	split(img, bgr);
	LUT(bgr[2], lut, bgr[2]);
	// merge result
	merge(bgr, result);

	// Create image for halo dark
	Mat halo(img.rows, img.cols, CV_32FC3, Scalar(0.3, 0.3, 0.3));
	// Create circle 
	circle(halo, Point(img.cols / 2, img.rows / 2), img.cols / 3, Scalar(1, 1, 1), -1);
	blur(halo, halo, Size(img.cols / 3, img.cols / 3));

	// Convert the result to float to allow multiply by 1 factor
	Mat resultf;
	result.convertTo(resultf, CV_32FC3);

	// Multiply our result with halo
	multiply(resultf, halo, resultf);

	// convert to 8 bits
	resultf.convertTo(result, CV_8UC3);

	// show result
	imshow("Lomograpy", result);

	// Release mat memory
	halo.release();
	resultf.release();
	lut.release();
	bgr[0].release();
	bgr[1].release();
	bgr[2].release();
}

void cartoonCallback(int state, void* userData)
{
	/** EDGES **/
	// Apply median filter to remove possible noise
	Mat imgMedian;
	medianBlur(img, imgMedian, 7);

	// Detect edges with canny
	Mat imgCanny;
	Canny(imgMedian, imgCanny, 50, 150);

	// Dilate the edges
	Mat kernel = getStructuringElement(MORPH_RECT, Size(2, 2));
	dilate(imgCanny, imgCanny, kernel);

	// Scale edges values to 1 and invert values
	imgCanny = imgCanny / 255;
	imgCanny = 1 - imgCanny;

	// Use float values to allow multiply between 0 and 1
	Mat imgCannyf;
	imgCanny.convertTo(imgCannyf, CV_32FC3);

	// Blur the edgest to do smooth effect
	blur(imgCannyf, imgCannyf, Size(5, 5));

	/** COLOR **/
	// Apply bilateral filter to homogenizes color
	Mat imgBF;
	bilateralFilter(img, imgBF, 9, 150.0, 150.0);

	// truncate colors
	Mat result = imgBF / 25;
	result = result * 25;

	/** MERGES COLOR + EDGES **/
	// Create a 3 channles for edges
	Mat imgCanny3c;
	Mat cannyChannels[] = { imgCannyf, imgCannyf, imgCannyf };
	merge(cannyChannels, 3, imgCanny3c);

	// Convert color result to float 
	Mat resultf;
	result.convertTo(resultf, CV_32FC3);

	// Multiply color and edges matrices
	multiply(resultf, imgCanny3c, resultf);

	// convert to 8 bits color
	resultf.convertTo(result, CV_8UC3);

	// Show image
	imshow("Result", result);

}

int main(int argc, const char** argv)
{
	CommandLineParser parser(argc, argv, keys);
	parser.about("Chapter 4. PhotoTool v1.0.0");
	//If requires help show
	if (parser.has("help"))
	{
		parser.printMessage();
		return 0;
	}

	String imgFile = "lena.jpg";

	// Check if params are correctly parsed in his variables
	if (!parser.check())
	{
		parser.printErrors();
		return 0;
	}

	// Load image to process
	img = imread(imgFile);

	// Create window
	namedWindow("Input");
	showHistoCallback(1,&img);
	cartoonCallback(1, &img);
	lomoCallback(1, &img);
	equalizeCallback(1, &img);

	// Create UI buttons
	//createButton("Show histogram", showHistoCallback, NULL, QT_PUSH_BUTTON, 0);
	//createButton("Equalize histogram", equalizeCallback, NULL, QT_PUSH_BUTTON, 0);
	//createButton("Lomography effect", lomoCallback, NULL, QT_PUSH_BUTTON, 0);
	//createButton("Cartonize effect", cartoonCallback, NULL, QT_PUSH_BUTTON, 0);

	// Show image
	imshow("Input", img);

	waitKey(0);
	return 0;

}

第七章 识别人脸覆盖面具
7.3 实时视频覆盖面具

// FACE DETECTION

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/objdetect/objdetect.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
	string faceCascadeName = "haarcascade_frontalface_alt.xml";
	CascadeClassifier faceCascade;

	if (!faceCascade.load(faceCascadeName))
	{
		cerr << "Error loading cascade file. Exiting!" << endl;
		return -1;
	}

	Mat faceMask = imread("timg.jpg");

	if (!faceMask.data)
	{
		cerr << "Error loading mask image. Exiting!" << endl;
	}

	// Current frame
	Mat frame, frameGray;
	Mat frameROI, faceMaskSmall;
	Mat grayMaskSmall, grayMaskSmallThresh, grayMaskSmallThreshInv;
	Mat maskedFace, maskedFrame;

	char ch;

	// Create the capture object
	// 0 -> input arg that specifies it should take the input from the webcam
	VideoCapture cap(0);

	// If you cannot open the webcam, stop the execution!
	if (!cap.isOpened())
		return -1;

	//create GUI windows
	namedWindow("Frame");

	// Scaling factor to resize the input frames from the webcam
	float scalingFactor = 0.75;

	vector<Rect> faces;

	// Iterate until the user presses the Esc key
	while (true)
	{
		// Capture the current frame
		cap >> frame;

		// Resize the frame
		resize(frame, frame, Size(), scalingFactor, scalingFactor, INTER_AREA);

		// Convert to grayscale
		cvtColor(frame, frameGray, CV_BGR2GRAY);

		// Equalize the histogram
		equalizeHist(frameGray, frameGray);

		// Detect faces
		faceCascade.detectMultiScale(frameGray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));

		// Draw green rectangle around the face
		for (int i = 0; i < faces.size(); i++)
		{
			Rect faceRect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);

			// Custom parameters to make the mask fit your face. You may have to play around with them to make sure it works.
			int x = faces[i].x - int(0.1*faces[i].width);
			int y = faces[i].y - int(0.0*faces[i].height);
			int w = int(1.1 * faces[i].width);
			int h = int(1.3 * faces[i].height);

			// Extract region of interest (ROI) covering your face
			frameROI = frame(Rect(x, y, w, h));

			// Resize the face mask image based on the dimensions of the above ROI
			resize(faceMask, faceMaskSmall, Size(w, h));

			// Convert the above image to grayscale
			cvtColor(faceMaskSmall, grayMaskSmall, CV_BGR2GRAY);

			// Threshold the above image to isolate the pixels associated only with the face mask
			threshold(grayMaskSmall, grayMaskSmallThresh, 230, 255, CV_THRESH_BINARY_INV);

			// Create mask by inverting the above image (because we don't want the background to affect the overlay)
			bitwise_not(grayMaskSmallThresh, grayMaskSmallThreshInv);

			// Use bitwise "AND" operator to extract precise boundary of face mask
			bitwise_and(faceMaskSmall, faceMaskSmall, maskedFace, grayMaskSmallThresh);

			// Use bitwise "AND" operator to overlay face mask
			bitwise_and(frameROI, frameROI, maskedFrame, grayMaskSmallThreshInv);

			// Add the above masked images and place it in the original frame ROI to create the final image
			add(maskedFace, maskedFrame, frame(Rect(x, y, w, h)));
		}

		// Show the current frame
		imshow("Frame", frame);

		// Get the keyboard input and check if it's 'Esc'
		// 27 -> ASCII value of 'Esc' key
		ch = waitKey(30);
		if (ch == 27) {
			break;
		}
	}

	// Release the video capture object
	cap.release();

	// Close all windows
	destroyAllWindows();

	return 1;
}

猜你喜欢

转载自blog.csdn.net/qq_28467367/article/details/89576382
今日推荐