第二章 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;
}