利用OpenCV自带的分类器识别面部及眼睛
OpenCV自带里许多分类器,可在haarcascades下载
获取面部
// 获取面部// image 为输入的OpenCV的格式的图像// out 为输出图像 <- 此处输出图像为裁剪下来的矩形面部图像bool get_face(cv::Mat image, cv::Mat &out){ // 将图像转为灰度图像,可提高识别精度 cv::Mat gray; cv::cvtColor(image, gray, CV_BGR2GRAY, 0); // 此处的rect为用来存储识别出的面部的定位 <- 这里为vector是因为识别的面部可能不止为一个 std::vector<cv::Rect> rect; // 初始化OpenCV的分类器 cv::CascadeClassifier cas = cv::CascadeClassifier("haarcascade_frontalface_default.xml"); cas.detectMultiScale(gray, rect, 1.15, 5); // 判断rect是否为空,为空的话就是没有被识别的面部 if (rect.empty()) { return false; } // 输出图像,这里的rect可能不止为一个(因为可能不止一张脸),所以实际中应该使用for循环 // 我这里用rect[0]为了简化 out = image(rect[0]); return true;}
获取眼睛
// 这里与上面相同(这里我只识别左眼,OpenCV还提供了其他文件可获取右眼和双眼)bool get_left_eye(cv::Mat image, cv::Mat &out){ // 之后与面部相同 cv::Mat gray; cv::cvtColor(image, gray, CV_BGR2GRAY, 0); std::vector<cv::Rect> rect; cv::CascadeClassifier cas = cv::CascadeClassifier("xml/haarcascade_lefteye_2splits.xml"); cas.detectMultiScale(gray, rect, 1.15, 5); if (rect.empty()) { return false; } out = image(rect[0]); return true;}
瞳孔定位
- 获取的眼睛图像
- 裁剪去除眉毛
- 伽马矫正提高图像对比度
- 转化为灰度图像
- 利用threshold进行阈值操作(此处可能会改为inRange,目前还在测试)
- 腐蚀
- 膨胀
- medianBlur平滑图像
- 检测关键点并画在图像上
// 定位眼球 -> 检测关键点std::vector<cv::KeyPoint> dector(cv::Mat image){ cv::SimpleBlobDetector::Params detector_params; detector_params.filterByArea = true; detector_params.maxArea = 1500; cv::Ptr<cv::SimpleBlobDetector> blob_dector = cv::SimpleBlobDetector::create(detector_params); std::vector<cv::KeyPoint> keypoints; blob_dector->detect(image, keypoints); return keypoints;} bool get_pupil(cv::Mat image, cv::Mat &out){ // width -> image.rows ; // height -> image.cols; // cut eyebrow 裁剪 去除眉毛 image = image(cv::Rect(image.cols / 10, image.rows / 2.5, image.cols * 8 / 10, image.rows / 2)); // Gamma correction/gamma nonlinearity 伽马校正 -> https://www.cnblogs.com/sdu20112013/p/11597171.html cv::Mat look_up_table(1, 256, CV_8U); uchar *p = look_up_table.ptr(); float gamma = 0.7; for (int i = 0; i < 256; ++i) p[i] = cv::saturate_cast<uchar>(pow(i / 255.0, gamma) * 255.0); cv::LUT(image, look_up_table, image); cv::Mat gray; // 转化为灰度图像 cv::cvtColor(image, gray, CV_BGR2GRAY, 0); // 阈值操作 cv::threshold(gray, gray, inRange_threshold, 255, CV_THRESH_BINARY); //膨胀及腐蚀 cv::erode(gray, gray, cv::Mat(), cv::Point(-1, -1), 2); cv::dilate(gray, gray, cv::Mat(), cv::Point(-1, -1), 3); // 平滑图像 cv ::medianBlur(gray, gray, 5); // 检测并画出关键点 cv::drawKeypoints(image, dector(gray), image, cv::Scalar(0, 0, 255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); out = image; return true;}
附录
OpenCV在ArchLinux上的使用
pacman -S opencv# vtk和hdf5为opencv的依赖,不安装编译会失败sudo pacman -S vtksudo pacman -Ss hdf5
Cmake文件
cmake_minimum_required(VERSION 3.14)project(eyedector)add_definitions(-std=c++11)# 这里只需要添加OpenCV的就能编译成功find_package(OpenCV REQUIRED)link_libraries(${OpenCV_LIBS})add_executable(out opencvtest.cpp)
利用安卓手机充当网络摄像头
手机安装这个IP Webcam,使用时会显示局域网中的地址
OpenCV中
cv::VideoCapture cap("http://192.168.0.xx:8080/video"); // 这里为网络摄像头的地址,需要在后面加上/videowhile (true){ cv::Mat frame; cap >> frame; cv::imshow("test", frame); if (cv::waitKey(1) == 27) { exit(0); }}
0 条评论