杭州高端定制网站,广告策划与营销,太原手机模板建站,企业申报系统之前写了一篇
利用OpenCV做个熊猫表情包吧_Leen的博客-CSDN博客
回想起来觉得有点太弱了#xff0c;意犹未尽#xff0c;每次使用需要自己去手动截取人脸#xff0c;清除黑边什么的才能使用demo去合成表情#xff0c;无奈之前由于安装的vs#xff0c;opencv版本都比较低…之前写了一篇
利用OpenCV做个熊猫表情包吧_Leen的博客-CSDN博客
回想起来觉得有点太弱了意犹未尽每次使用需要自己去手动截取人脸清除黑边什么的才能使用demo去合成表情无奈之前由于安装的vsopencv版本都比较低也懒得再折腾。
恰逢前些天电脑硬盘坏了数据丢了一切都要重装那直接高配走起VS2022OpenCV4.8,既然环境都有了于是有空的时候就改进了一下让它利用opencv做简单的人脸识别自动去图片中识别、提取人脸同时去做黑边清理工作自动化程度更高用起来更省事儿~
原理呢就是在处理原始图片的流程中加入了面部识别将面部单独切出来同时对面部图片做黑边清晰处理然后再进行表情的合成工作下面介绍一下具体过程
首先是识别到用户输入的原图 利用opencv进行面部识别 灰度化图片后提取面部并清理黑边 再将面部跟熊猫脸进行融合 下面介绍关键步骤的代码
初始化面部识别
int InitFaceDetect()
{if (!faceCascade.load(D:\\Workspace\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_default.xml)) {cout 人脸检测级联分类器没找到 endl;return -1;}if (!eyes_Cascade.load(D:\\Workspace\\opencv\\build\\etc\\haarcascades\\haarcascade_eye_tree_eyeglasses.xml)) {cout 眼睛检测级联分类器没找到 endl;return -1;}return 0;
}用到的两个xml特征文件均为openCV提供。
清楚灰度图像中的深色边角区域
/************************************************************************/
/* 消除图片四周的黑色边角区域 */
/************************************************************************/Mat RemoveBlackCorner(Mat img)
{int i, j;int h img.size().height;int w img.size().width;if (img.channels() 1) //灰度图片{for (j 0; j h; j){for (i 0; i w; i){if (img.atuchar(j, i) 110){img.atuchar(j, i) 255;}else{break;}}for (i w - 1; i 0; i--){if (img.atuchar(j, i) 110){img.atuchar(j, i) 255;}else{break;}}}for (i 0; i w; i){for (j 0; j h; j){if (img.atuchar(j, i) 110){img.atuchar(j, i) 255;}else{break;}}for (j h - 1; j 0; j--){if (img.atuchar(j, i) 110){img.atuchar(j, i) 255;}else{break;}}}}return img;
}
人脸识别以及将加工后的人脸存成临时文件
bool parse_cmd(int argc, char* argv[])
{if (argc 3){return false;}g_str_src string(argv[1]);g_str_bg string(argv[2]);return true;
}string GetFolderFromFile(string strFile)
{size_t last_slash strFile.find_last_of(\\);std::string directory strFile.substr(0, last_slash);return directory;
}int DetectFace(Mat img, Mat imgGray) {namedWindow(src, WINDOW_AUTOSIZE);vectorRect faces, eyes;faceCascade.detectMultiScale(imgGray, faces, 1.2, 5, 0, Size(30, 30));int retVal -1;//目前只取一个脸if (faces.size() 0) {for (size_t i 0; i faces.size(); i) {//框出人脸位置rectangle(img, Point(faces[i].x faces[i].width / 8, faces[i].yfaces[i].height / 8), Point(faces[i].x faces[i].width*7/8, faces[i].y faces[i].height * 7 / 8), Scalar(0, 0, 255), 1, 8);cout faces[i] endl;//将人脸从灰度图中抠出来Mat face_ imgGray(faces[i]);//缩小一点默认取的矩形比较大Rect rect(Point(faces[i].width / 8, faces[i].height / 8),Point(faces[i].width * 7 / 8, faces[i].height * 7/ 8));Mat ROI face_(rect);//RemoveBlackBorder(ROI, ROI);Mat imgOut RemoveBlackCorner(ROI);//RemoveBlackBorder(ROI, imgOut);imwrite(g_str_face, imgOut);retVal 0;eyes_Cascade.detectMultiScale(face_, eyes, 1.2, 2, 0, Size(30, 30));for (size_t j 0; j eyes.size(); j) {Point eye_center(faces[i].x eyes[j].x eyes[j].width / 2, faces[i].y eyes[j].y eyes[j].height / 2);int radius cvRound((eyes[j].width eyes[j].height) * 0.25);circle(img, eye_center, radius, Scalar(65, 105, 255), 4, 8, 0);}}}imshow(src, img);return retVal;
}
主逻辑流程 int main(int argc, char* argv[])
{if (!parse_cmd(argc, argv)){cout command error endl;return -1;}if (InitFaceDetect() ! 0){return -1;}//string strDirBase GetFolderFromFile(g_str_src);Mat img_src imread(g_str_src);Mat img_background imread(g_str_bg);g_str_face strDirBase \\tmp_face.jpg;
#ifdef _DBG_SHOWnamedWindow(img_src);imshow(img_src, img_src);
#endifMat img_gray;cvtColor(img_src, img_gray, COLOR_BGR2GRAY); //图像灰度化int nFace DetectFace(img_src, img_gray);waitKey(3000);
#ifdef _DBG_SHOWnamedWindow(gray, WINDOW_NORMAL);imshow(gray, img_gray);
#endif// 按照背景图大小等比缩放Size dsize Size(img_background.cols * 0.55, img_background.rows * 0.55);//判断一下是否自动检测到了人脸Mat img_face;if (nFace 0) {cout opencv find face,get face. endl;img_face imread(g_str_face);}else{cout can not find face.use image user input. endl;img_face img_gray;}resize(img_face, img_face, dsize, 1, 1, INTER_AREA);//输出缩放后效果图并重新加载Mat img_face2;threshold(img_face, img_face2, 105, 255, THRESH_BINARY);imwrite(strDirBase \\tmp.jpg, img_face2);//imshow(img_face2, img_face2);Mat img_face3 imread(strDirBase \\tmp.jpg);//居中粘合两图Rect roi_rect Rect((img_background.cols - img_face3.cols) / 2, (img_background.rows - img_face3.rows) / 2, img_face3.cols, img_face3.rows);img_face3.copyTo(img_background(roi_rect));//显示并输出imshow(mixed, img_background);imwrite(g_str_src .emoji.jpg, img_background);waitKey(5000);destroyAllWindows();return 0;
}