IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> OpenCV学习笔记之图像处理与人脸检测 -> 正文阅读

[人工智能]OpenCV学习笔记之图像处理与人脸检测

1.1访问摄像头或者读取图片和视频流:?

? ? ? ? 在OpenCV中,通过cv::VideoCapture对象的open()方法可访问摄像头或者相机设备。

VideoCapture初始化:

????????bool VideoCapture::open(const string& filename)//开视频文件

????????bool VideoCapture::open(int device) //开摄像头

????????bool VideoWriter::isOpened() //若初始化成功返回true,失败返回false

imread与imshow:

????????Mat cv::imread ( const String & filename, int flags = IMREAD_COLOR )

????????参数1 filename, 读取的图片文件名,可以使用相对路径或者绝对路径,但必须带完整的文件扩展名(图片格式后缀)

????????参数2 flags, 一个读取标记,用于选择读取图片的方式,默认值为IMREAD_COLOR,flag值的设定与用什么颜色格式读取图片有关

????????void imshow(const string& winname, InputArray mat);

????????参数1 winname,生成的窗口的名称

? ? ? ? 参数2 mat 懂的都懂

????????void nameWindow(const string& winname,int flags = WINDOW_AUTOSIZE) //新建一个窗口

????????参数1:新建的窗口的名称。自己随便取。

????????参数2:窗口的标识,一般默认为WINDOW_AUTOSIZE 。

????????WINDOW_AUTOSIZE 窗口大小自动适应图片大小,并且不可手动更改。(上面图1就是使用的它)

????????WINDOW_NORMAL 用户可以改变这个窗口大小(上面图2就是使用的它)

????????WINDOW_OPENGL 窗口创建的时候会支持OpenGL
?

????????int cv::waitKey ( int delay = 0 ) ????????//等待一个按键,等待的时间取决于参数,0则无限等待,返回按键的ASCII值

#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void main(int argc,char *argv[]){
    auto cameraNumber = 0;
    if(argc > 1){
        cameraNumber = atoi(argv[1]);
    }
    //这里尝试去打开摄像头设备
    VideoCapture camera;
    camera.open(cameraNumber);
    if(!camera.isOpened()){
        cerr<<"ERROR : cannot open the camera"<<endl;
        exit(1);
    }
    //设置摄像头的分辨率 640 * 480
    camera.set(CV_CAP_PROP_FRAME_WIDTH,640);
    camera.set(CV_CAP_PROP_FRAME_HEIGHT,480);
}

? ? ? ? 由于版本变量的更名,若使用CV_CAP_PROP_FRAME_WIDTH发生报错,则去掉前面的CV_即可。

? ? ? ? cerr:输出到标准错误的ostream对象,常用于程序错误信息(重定向不会影响cerr)

? ? ? ?或者简单的使用如下的方式;

#include<iostream>
#include<opencv2/opencv.hpp>
#include <opencv2\imgproc\types_c.h>
void main(int argc, char *argv[]) {
	Mat video;
	VideoCapture capture(0);
	while (1) {
		capture >> video;
		imshow("test",video);
		waitKey(30);
	}
	return;
}

1.2桌面应用程序的相机处理主循环(实时相机应用程序)

? ? ? ? 实时相机应用程序的骨架:


    while (true) {
		Mat cameraFrame;
		camera >> cameraFrame;
		if (cameraFrame.empty()) {
			cerr << "error!! cannot grap a camera frame" << endl;
			exit(1);
		}
		//创建一个新的空白的画面,待会让程序画上去
		Mat displayedFrame(cameraFrame.size(), CV_8UC3);

		//将摄像机的画面画上去
		cartoonifyImage(cameraFrame,displayedFrame);
		//显示画面
		imshow("Cartoonifier", displayedFrame);

		auto keypress = waitKey(20);
		if (keypress == 27) {
			//若是返回键,则退出
			break;
		}
	}

? ? ? ? 1.2.1卡通化图像

????????????????图像中灰度变化较大的非连续像素可以看做是边缘,若要将图片转化为黑白图画,可用边缘检测滤波器,若要获得彩色绘画,可采用边缘保留滤波器(双边滤波器),使用滤波器之前,需要对图像去噪,可使用中值滤波器来去噪。

????????这里我们采用Laplacian边缘滤波器,该滤波器使用灰度图像,因此需要将OpenCV的默认BGR格式转化为灰度。

void cartoonifyImage(Mat& src, Mat& dst)
{
	Mat gray;
	cvtColor(src, gray, CV_BGR2GRAY);
	const int MEDIAN_BLUR_FILTER_SIZE = 7;
	medianBlur(gray, gray, MEDIAN_BLUR_FILTER_SIZE); // 中值
	Mat edges;
	const int LAPLACIAN_FILTER_SIZE = 5;
	Laplacian(gray, edges, CV_8U, LAPLACIAN_FILTER_SIZE); // 拉普拉斯
	Mat mask;
	const int EDGES_THRESHOLD = 80;
	threshold(edges, mask, EDGES_THRESHOLD, 255, THRESH_BINARY_INV); //二值化

	// 图片缩小
	Size size = src.size();
	Size smallSize;
	smallSize.width = size.width / 2;
	smallSize.height = size.height / 2;
	Mat smallImg = Mat(smallSize, CV_8UC3);
	resize(src, smallImg, smallSize, 0, 0, INTER_LINEAR);

	// 双边滤波
	Mat tmp = Mat(smallSize, CV_8UC3);
	int repetitions = 7;
	for (int i = 0; i < repetitions; i++)
	{
		int ksize = 9;
		double sigmaColor = 9;
		double sigmaSpace = 7;
		bilateralFilter(smallImg, tmp, ksize, sigmaColor, sigmaSpace);
		bilateralFilter(tmp, smallImg, ksize, sigmaColor, sigmaSpace);
	}

	// 图像复原
	Mat bigImg;
	resize(smallImg, bigImg, size, 0, 0, INTER_LINEAR);
	dst.setTo(0);
	bigImg.copyTo(dst, mask);

}

? ? ??

这里的CV_BGR2GRAY一直报错,说未定义标识符,搞了很久,只需要引入头文件#include <opencv2\imgproc\types_c.h>?即可。

? ? ? ? ?Sample:

?
1.2.2邪恶模式

????????进行两次Scharr滤波即可

void evilImage(Mat& src, Mat& dst)
{
	Mat gray, mask;
	cvtColor(src, gray, CV_BGR2GRAY);
	const int MEDIAN_BLUR_FILTER_SIZE = 7;
	medianBlur(gray, gray, MEDIAN_BLUR_FILTER_SIZE);

	Mat edges, edges2;
	Scharr(gray, edges, CV_8U, 1, 0);
	Scharr(gray, edges2, CV_8U, 1, 0, -1);
	edges += edges2;
	const int EVIL_EDGE_THRESHOLD = 12;
	threshold(edges, mask, EVIL_EDGE_THRESHOLD, 255, THRESH_BINARY_INV);
	medianBlur(mask, mask, 3);
	imshow("1", mask);
	dst.setTo(0);
	src.copyTo(dst, mask);
}

sample:

使用人脸模块进行人脸特征点及姿态检测

? ? ? ? 2.1人脸的特征点检测

? ? ? ? 特征点的检测先从人脸检测开始,在图像中寻找人脸以及范围(边界框),最简单

的方法,只需使用core模块中提供的cv::CascadeClassifier类即可。

? ? ? ? 下面是一个具有级联分类器的简单辅助函数来检测人脸:

void faceDetector(const Mat &image,vector<Rect> &faces,CascadeClassifier &face_cascade) {

	Mat gray;
	//灰度图像是最适合人脸检测的                                                                                     
	if (image.channels() > 1) {
		cvtColor(image, gray, COLOR_BGR2GRAY);
	}
	else {
		gray = image.clone();
	}
	equalizeHist(gray,gray);	//对图像进行直方图均衡化
	faces.clear();
	face_cascade.detectMultiScale(gray,faces,1.4,3,CASCADE_SCALE_IMAGE+CASCADE_FIND_BIGGEST_OBJECT);
}

这里注意最后一个语句的倒数第二第三参数,金字塔尺度因子和临近点数量。金字塔尺度因子用于创建图像金字塔,检测器将在其中查找人脸,在生成图像金字塔的每一步中,图像按此比例因子缩小,因此较小的因子(接近1.0)将导致生成更多的图像,但是却意味着更长的运行时间,结果更精准,第二个参数控制了邻近人脸的下限,若检测出至少三个相邻的人脸整个分类器只返回一个人脸。

? ? ? ? 首先要用OpenCV提供的模型来初始化级联分类器,这里对正面人脸标定训练分类器(序列化模型的XML在&OPENCV_ROOT/data/haarcascades目录)。

	const string cascade_name ="E:/opencv/opencv/sources/data/haarcascades/haarcascades_frontalface_default.xml";
	CascadeClassifier face_cascade;
	if (not face_cascade.load(cascade_name)) {
		cerr << "cannot load cascade classifier from file" << cascade_name << endl;
		return -1;
	}

	vector<Rect> faces;
	faceDetector(cameraFrame, faces, face_cascade);
	if (faces.size() == 0) {
		cerr << "cannot detect any faces in the image" << endl;
		return -1;
	}

? ? ? ? 确定边界之后,还要对cv::face::Facemark对象进行初始化:

????????这里的#include<opencv2/face.hpp>一般会报错,这是因为而opencv3的人脸识别库等contrib模块已经不再内置了,这里提供了下载的地址,解压到build/include/opencv2中即可。https://github.com/opencv/opencv_contrib/releases

#include<opencv2/face.hpp>
using namespace cv::face;

// ............
	
    const string facemark_filename = "fata/lbfmodel.yaml";
	Ptr<Facemark> facemark = createFacemarkLBF();
	facemark->loadModel(facemark_filename);
	cout << "Loaded facemark LBF model" << endl;

? ? ? ? 初始化后,使用facemark对象及其fit函数来查找面部形状。

	vector<Rect> faces;
	faceDetector(cameraFrame, faces, face_cascade);
	if (faces.size() != 0) {
		rectangle(cameraFrame, faces[0], Scalar(255, 0, 0), 2);
		vector<vector<Point2f>> shapes;
		if (facemark->fit(img, faces, shapes)) {
			drawFacemarks(img, shapes[0], cv::Scalar(0, 0, 255));
		}
	}
	else {
		cout << "faces not detected" << endl;
	}

sample:

?当然,将图片改成摄像头流,可以实时捕获到摄像头中出现的人脸。

下面是代码实例

#include <opencv2\imgproc\types_c.h>
#include<opencv2/opencv.hpp>
#include<opencv2/face.hpp>
#include<iostream>
using namespace std;
using namespace cv;
using namespace cv::face;

void faceDetector(const Mat &image,vector<Rect> &faces,CascadeClassifier &face_cascade) {

	Mat gray;
	//灰度图像是最适合人脸检测的                                                                                     
	if (image.channels() > 1) {
		cvtColor(image, gray, COLOR_BGR2GRAY);
	}
	else {
		gray = image.clone();
	}
	equalizeHist(gray,gray);	//对图像进行直方图均衡化
	faces.clear();
	face_cascade.detectMultiScale(gray,faces,1.3,3,CASCADE_SCALE_IMAGE+CASCADE_FIND_BIGGEST_OBJECT);
}
void evilImage(Mat& src, Mat& dst)		//邪恶模式
{
	Mat gray, mask;
	cvtColor(src, gray, CV_BGR2GRAY);
	const int MEDIAN_BLUR_FILTER_SIZE = 7;
	medianBlur(gray, gray, MEDIAN_BLUR_FILTER_SIZE);

	Mat edges, edges2;
	Scharr(gray, edges, CV_8U, 1, 0);
	Scharr(gray, edges2, CV_8U, 1, 0, -1);
	edges += edges2;
	const int EVIL_EDGE_THRESHOLD = 12;
	threshold(edges, mask, EVIL_EDGE_THRESHOLD, 255, THRESH_BINARY_INV);
	medianBlur(mask, mask, 3);
	imshow("1", mask);
	dst.setTo(0);
	src.copyTo(dst, mask);
}


void cartoonifyImage(Mat& src, Mat& dst)	//卡通化图像
{
	Mat gray;
	cvtColor(src, gray, CV_BGR2GRAY);
	const int MEDIAN_BLUR_FILTER_SIZE = 7;
	medianBlur(gray, gray, MEDIAN_BLUR_FILTER_SIZE); // 中值
	Mat edges;
	const int LAPLACIAN_FILTER_SIZE = 5;
	Laplacian(gray, edges, CV_8U, LAPLACIAN_FILTER_SIZE); // 拉普拉斯
	Mat mask;
	const int EDGES_THRESHOLD = 80;
	threshold(edges, mask, EDGES_THRESHOLD, 255, THRESH_BINARY_INV); //二值化

	// 图片缩小
	Size size = src.size();
	Size smallSize;
	smallSize.width = size.width / 2;
	smallSize.height = size.height / 2;
	Mat smallImg = Mat(smallSize, CV_8UC3);
	resize(src, smallImg, smallSize, 0, 0, INTER_LINEAR);

	// 双边滤波
	Mat tmp = Mat(smallSize, CV_8UC3);
	int repetitions = 7;
	for (int i = 0; i < repetitions; i++)
	{
		int ksize = 9;
		double sigmaColor = 9;
		double sigmaSpace = 7;
		bilateralFilter(smallImg, tmp, ksize, sigmaColor, sigmaSpace);
		bilateralFilter(tmp, smallImg, ksize, sigmaColor, sigmaSpace);
	}

	// 图像复原
	Mat bigImg;
	resize(smallImg, bigImg, size, 0, 0, INTER_LINEAR);
	dst.setTo(0);
	bigImg.copyTo(dst, mask);

}

int main(int argc, char *argv[]) {

//	Mat cameraFrame;
//	const string filename = "E:/imgsource/3.jpg";
//	cameraFrame = imread(filename,1);
	Mat cameraFrame;
	VideoCapture camera(0);
	const string cascade_name = "E:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml";
	CascadeClassifier face_cascade;
	if (not face_cascade.load(cascade_name)) {
		cout << "cannot load cascade classifier from file   " << cascade_name << endl;
		return -1;
	}
	vector<Rect> faces;
	while (1) {
		camera >> cameraFrame;
		faceDetector(cameraFrame, faces, face_cascade);
		for (int i = 0; i < faces.size(); ++i)
			rectangle(cameraFrame, faces[i], Scalar(255, 0, 0), 2);

		imshow("test", cameraFrame);
		auto keypress=waitKey(10);
		if (keypress == 21) {
			break;
		}
	}
	return 0;
}

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-07-23 10:47:03  更:2021-07-23 10:47:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/22 10:52:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码