OpenCV人脸识别C++源码分析

2023-10-31

#include "cv.h"
#include "highgui.h"  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <assert.h>  
#include <math.h>  
#include <float.h>  
#include <limits.h>  
#include <time.h>  
#include <ctype.h>  
   
#include <android/log.h>  
#include <study_opencv_FaceRec.h>  
#include <jni.h>  
   
#define   LOG_TAG      "opencv_face_detect"  
#define   LOGI(...)   __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)  
#define   LOGE(...)   __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)  
   
static CvMemStorage* storage = 0;  
static CvHaarClassifierCascade* cascade = 0;  
void detect_and_draw( IplImage* image );  
const char* cascade_name =  
      "haarcascade_frontalface_alt.xml";  
 
 
char* jstring2String(JNIEnv*, jstring);  
//主要功能函数
int captureFromImage(char* xml, char* filename, char* outfile)  
{  
      LOGI("begin: ");  
       // we just detect image  
    // CvCapture* capture = 0;  
    //opencv的结构体IplImage指针,详见http://baike.baidu.com/view/3083269.htm
      IplImage *frame, *frame_copy = 0;  
      const char* input_name = "lina.png";  
      if(xml != NULL)  
      {  
            cascade_name = xml;    
      }  
      if(filename != NULL)  
      {  
            input_name = filename;  
      }  
      LOGI("xml=%s,filename=%s", cascade_name, input_name);  
       // load xml   
            LOGI("ERROR: Could not load classifier cascade\n" );  
            FILE * fp = fopen(input_name,"w");  
            if(fp == NULL){  
                  LOGE("create failed");  
            }  
            return -1;  
      }  
//开辟内存空间
      storage = cvCreateMemStorage(0);  
    // cvNamedWindow( "result", 1 );  
//载入图像
      IplImage* image = cvLoadImage( input_name, 1 );  
      if( image )  
      {  
            LOGI("load image successfully");  
            detect_and_draw( image );  
            // cvWaitKey(0);  
            if(outfile != NULL)  
            {  
                  LOGI("after detected save image file");  
                  cvSaveImage(outfile, image);//把图像写入文件  
            }  
//释放内存
            cvReleaseImage( &image );  
      }  
      else  
      {  
            LOGE("can't load image from : %s ", input_name);  
      }  
}  
//主要识别函数
void detect_and_draw( IplImage* img )  
{  
      static CvScalar colors[] =    
      {  
            {{0,0,255}},  
            {{0,128,255}},  
            {{0,255,255}},  
            {{0,255,0}},  
            {{255,128,0}},  
            {{255,255,0}},  
            {{255,0,0}},  
            {{255,0,255}}  
      };  
      double scale = 2;  
//保存灰度图像,8位,单通道
      IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 ); 
//对一个double型的数进行四舍五入,并返回一个整型数 
      IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),  
                                      cvRound (img->height/scale)),  
                                8, 1 );  
      int i;  
//将BGR图像转换为灰度图像
      cvCvtColor( img, gray, CV_BGR2GRAY ); 
//缩放源图像到目标图像 
      cvResize( gray, small_img, CV_INTER_LINEAR ); 
//用来使灰度图象直方图均衡化,该方法归一化图像亮度和增强对比度。
      cvEqualizeHist( small_img, small_img );  
      cvClearMemStorage( storage );  
      if( cascade )  
      {   //计时
            double t = (double)cvGetTickCount();  
//storage 用来存储检测到的一序列候选目标矩形框的内存区域。
//scale_factor 在前后两次相继的扫描中,搜索窗口的比例系数。例如1.1指将搜索窗口依次扩大10%
//min_neighbors 构成检测目标的相邻矩形的最小个数(缺省-1)。
//flags 操作方式。当前唯一可以定义的操作方式是 CV_HAAR_DO_CANNY_PRUNING。如果被设定,函数利用Canny边缘检测器来排除一些边缘很少或者很多的图像区域
//min_size 检测窗口的最小尺寸
            CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,  
                                                                  1.1, 2, 0,  
                                                                  cvSize(30, 30) ); 
 
            t = (double)cvGetTickCount() - t;  
            LOGI( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );  
//便利检测结果,在图上画圈标记
            for( i = 0; i < (faces ? faces->total : 0); i++ )  
            {  
                  CvRect* r = (CvRect*)cvGetSeqElem( faces, i );  
                  CvPoint center;  
                  int radius;  
                  center.x = cvRound((r->x + r->width*0.5)*scale);  
                  center.y = cvRound((r->y + r->height*0.5)*scale);  
                  radius = cvRound((r->width + r->height)*0.25*scale);  
//画圈
                  cvCircle( img, center, radius, colors[i%8], 3, 8, 0 );  
            }  
      }  
      // cvShowImage( "result", img ); 
//释放内存 
      cvReleaseImage( &gray );  
      cvReleaseImage( &small_img );  
}  
   
JNIEXPORT void JNICALL Java_study_opencv_FaceRec_detect  
   (JNIEnv * env, jobject obj, jstring xml, jstring filename, jstring outfile)  
{  
      LOGI("top method invoked! ");
 
      captureFromImage(jstring2String(env,xml), jstring2String(env,filename), jstring2String(env,outfile));  
   
}  
   
//jstring to char*  
   
char* jstring2String(JNIEnv* env, jstring jstr)  
{  
      if(jstr == NULL)  
      {  
            LOGI("NullPointerException!");  
            return NULL;  
      }  
      char* rtn = NULL;  
//得到Java中的类
      jclass clsstring = env->FindClass("java/lang/String");  
//声明一个jstring类型对象,内容为编码方式
      jstring strencode = env->NewStringUTF("utf-8");  
//得到java类中某方法的ID
      jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
//用ID调用java类的方法,执行。参数:输入字符串,方法ID,编码方式(jstring),返回byte数组(jbyteArray)。
      jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);  
//得到数组长度(jsize)
      jsize alen = env->GetArrayLength(barr);  
//声明指针,指向byte数组内容
      jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);  
      if (alen > 0)  
      {  
//为(char*)指针 rtn 申请空间,多申请一个char位置
            rtn = (char*)malloc(alen + 1);  
//内存拷贝,将原byte数组内容copy到char*指针所指位置。长度为alen
            memcpy(rtn, ba, alen);  
//将最后一个字符设置为0,表示为nuRFll
            rtn[alen] = 0;  
      }  
//释放java类中的数组空间
      env->ReleaseByteArrayElements (barr, ba, 0);  
      LOGI("char*=%s",rtn);  
      return rtn;  
}  


FROM: http://blog.sina.com.cn/s/blog_5b2469f20100zvmx.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCV人脸识别C++源码分析 的相关文章

  • react 图片剪切(react-easy-crop)

    antd 官方提供的剪切组件 仅支持本地图片的剪切和上传 import Upload from antd import ImgCrop from antd img crop import type RcFile UploadFile Upl
  • Angular中父子组件传值@Input @Output @ViewChild最全面最简单的总结

    父组件传递给子组件 值传递方式 Input既可以传递数据也可以传递方法 传递数据 不举例了 传递方法 父组件定义方法 parentRun alert 这是父组件的 run 方法 调用子组件时传入当前方法 是传递方法不是调用方法
  • Element UI el-input 只能输入大于0的正整数

    当输入值以0开头或者不为0 9的整数时 则用 替换掉 g表示全局匹配 则所有匹配项都会被替换掉 效果为不能输入以0开头或不为正整数的值
  • Oracle 基本 SQL 语句查询手册(1):增删改查

    关于SQL语法学习 这里有一份图文并茂的教程 点击此处 针对文字内容进行简化 通过注释 解释语句含义 本文的重点在于Oralce中写法 当然了 大部分写法都是通用的 查询手册 没有配图 各位看官见谅 创建临时表 用于测试 练习基本语句的写法
  • 什么是护网(HVV)?需要什么技术?(内附护网超全资料包)

    一 什么是护网行动 护网行动是以公安部牵头的 用以评估企事业单位的网络安全的活动 具体实践中 公安部会组织攻防两方 进攻方会在一个月内对防守方发动网络攻击 检测出防守方 企事业单位 存在的安全漏洞 通过与进攻方的对抗 企事业单位网络 系统以
  • ping 命令数字波动大的解决方法

    win10ping值不稳定怎么办 我们可以通过ping来判断网络是否流畅 一般来说在ping界面 只要 时间 后面的数值在10以内那么网速就是稳定的 最近在win10系统中有用户反应网速慢的心想 在使用ping进行ping一些网站的时候果然
  • easyUI前端框架tree(树)后台实现(树形菜单一)——java

    转载请标明出处 https blog csdn net men ma article details 106847165 本文出自 不怕报错 就怕不报错的小猿猿 的博客 easyUI前端框架tree 树 后台实现 树形菜单一 java 利用
  • 引领语言智能革命的巨型语言模型 ChatGPT PK Google Bard , Anthropic

    ChatGPT是由OpenAI公司训练的一个大型语言模型 它可以生成人类可读的文本 这是一个基于Transformer架构的预训练模型 可以进行语言生成和语言理解任务 OpenAI公司在2020年推出了ChatGPT 它是世界上最大的语言模
  • 多级代理下Nginx透传真实IP

    文章目录 多级代理下Nginx透传真实IP Nginx RealIP获取真实IP 多级代理下Nginx透传真实IP 1 基于代理 七层负载均衡 情况下 透传客户端的真实IP 环境 10 0 0 5 proxy node1 一级代理10 0
  • ERROR: Failed building wheel for dlib python 3.10 无法下载 pip/conda install dlib库的解决办法

    如果您在Python 3 10版本中无法使用pip安装dlib库 可能是由于以下原因之一 您的Python版本不支持dlib库 请确保您的Python版本与dlib库的版本兼容 您的pip版本不支持dlib库 请确保您的pip版本与dlib
  • plc模拟量与通信控制应用实践_第三版电气控制与PLC应用模块三教材答案

    很高兴这期为你分享干货 让你在困难中找到解决的线索 模块三答案 任务一 思考与练习 1 PLC 主要应用在哪些场合 答 1 开关量逻辑控制 2 模拟量过程控制 3 运动控制 4 现场数据采集处理 5 通讯联网 多级控制 2 PLC 的基本结
  • 文件打包发布

    本文基于VS Qt和VTK环境开发软件 生成可执行文件 通过软件ProcessExplorer查找发布软件所需要的库和通过软件VNISEdit打包该可执行文件 1 添加QT所需要的环境 2 添加VTK所需要的环境 3 文件打包发布 1 添加
  • windows上同时安装两个版本的mysql数据库

    在实际开发中 一些低版本数据库 不支持一些特殊的sql语句 因此高版本数据库数据导入低版本的时候就会出问题 因此 在一些特殊情况下 低版本数据库不能动 高版本mysql数据又无法导入低版本mysql 我们不得不在同一台机器上安装两个版本my
  • 关于使用get请求传递base64的注意事项

    关于使用get请求传递base64的注意事项 我们知道 get请求和post请求是有区别的 1 GET请求是用来请求获取数据 POST一般作为发送数据到后台时使用 并不返回数据 2 GET请求也可传参到后台 但是其参数在浏览器的地址栏的ur
  • Lambdda表达式( Java 8 )

    在Java的语言世界里面 除了基本的数据类型 一切都是对象 例如 String字符串 每个对象实例 数组这些都是对象 在Java中方法是不能完全独立存在的 不能将方法作为参数或者返回值给实例 注意 方法 Method 函数 Function

随机推荐

  • SAP 下载SMW0模板文件并附加数据导入到Excel示例

    1 效果 下载模板后 导入内表数据到Excel 2 代码 关键代码DATA excel TYPE ole2 object Excel object worksheet TYPE ole2 object workbooks TYPE ole2
  • js获取地址栏参数function封装

    获取地址栏参数 function GetQueryString name var reg new RegExp name var r window location search substr 1 match reg if r null r
  • 《每日一题》NO.14:名词解释 后端设计篇

    芯司机 每日一题 会每天更新一道IC面试笔试题 其中有些题目已经被很多企业参考采用了哦 聪明的你快来挑战一下吧 今天是第14题 各大IC公司的笔试题经常会从名词解释开始 所以我们给大家精心准备了50个名词解释题 每天更新10个 务求将名词解
  • 2021-3-26 米斯特安全团队视频笔记二(含PHP)

    DOS命令 常用Dos命令 1 通配符 号 代替0或多个字符 号 代替一个字符 2 查看命令 3 操作命令 信息搜集 whois 备案 PHP 变量 命名格式 美元字符开头 字母 下划线 不能跟数字 特殊符号 name key 常量 通过d
  • HTML <u> 标签

    实例 使用 u 标签为文本添加下划线 p 如果文本不是超链接 就不要 u 对其使用下划线 u p 定义和用法 u 标签可定义下划线文本 浏览器支持 元素 Chrome IE Firefox Safari Opera u Yes Yes Ye
  • maven jetty 插件的使用

    jetty插件的安装 首先打开项目的pom xml文件 然后找到build节点 在其中添加plugins节点 然后再添加如下的插件
  • 清华大学uCore-操作系统内核实现

    本系列文章是学堂在线清华大学操作系统慕课 课程实验 实现uCore内核的讲义总结及个人攻略 如果有对课程感兴趣的朋友建议看原课程 前置知识 即提前要掌握的知识 C语言和汇编语言 数据结构和算法 计算机组成原理 实验内容 Lab1 uCore
  • Rust 学习笔记之内存管理与生命周期

    内存管理是理解低级语言 和硬件相关的 的基础概念 低级语言没有提供自动内存管理的解决方案 例如内置垃圾回收器 它要求程序员自己在程序中管理内存 理解内存何时何地被创建和释放可以使得程序员构建出一个高效 安全的软件 然而 低级语言的大量错误也
  • 设计模式第八讲:观察者模式和中介者模式详解

    一 观察者模式 1 背景 在现实世界中 许多对象并不是独立存在的 其中一个对象的行为发生改变可能会导致一个或者多个其他对象的行为也发生改变 例如 某种商品的物价上涨时会导致部分商家高兴 而消费者伤心 还有 当我们开车到交叉路口时 遇到红灯会
  • perl中CPAN的安装

    最近一直在学习nagios监控的知识 因为使用SNMP方式进行监测 而nagios的SNMP监测文件是pl结尾的perl脚本 所以需要安装CPAN 下面就安装CPAN的安装记录步骤如下 首先安装perl 可以通过yum方式进行安装 这样减少
  • STM32F0不同代码区跳转时总失败…这些操作你做对了吗?

    STMCU官网更新了一则实战经验文件 文章以STM32F0为例 就芯片内 从BOOT区跳转到APP区 从APP区跳转到新APP区 从APP区跳回BOOT区 的跳转问题做一些交流与介绍 更多信息请前往官网详情页 文章导读 对于STM32用户
  • java 顺序结构循环队列(源代码)

    1 import java util Arrays 2 public class LoopQueue
  • python模拟登入某平台+破解验证码

    概述 python模拟登录平台 遇见验证码识别 用最简单的方法selenium da破解验证码 来自动登录平台 详细 python用selenium xpath模拟登录 破解验证码 先随便找个小说平台用户登陆 书海小说网用户登陆 书海小说网
  • Golang-指针(pointer)

    1 概念 指针 指向内存地址的变量 指针用来存储变量的内存地址 Go 语言定义变量必须声明数据类型 因为不同数据类型的数据占用不同的存储空间 导致内存地址分配大小各不相同 所有指针只能存放同一类型变量的内存地址 指针分为两种 类型指针和切片
  • Android RecyclerView实现吸顶动态效果,详细分析

    文章目录 一 ItemDecoration 二 实现RecyclerView吸顶效果 1 实现一个简单的RecyclerView 2 通过ItemDecoration画分割线 3 画出每个分组的组名 4 实现吸顶效果 完整demo 链接 h
  • Python 数组的长度

    数组 Array 是有序的元素序列 若将有限个类型相同的变量的集合命名 那么这个名称为数组名 组成数组的各个变量称为数组的分量 也称为数组的元素 有时也称为下标变量 用于区分数组的各个元素的数字编号称为下标 数组是在程序设计中 为了处理方便
  • xss-labs-master 第六关到第十关通关

    要想看前面的五关请看xss labs master 第一关到第五关通关 Level 6 进入题目废话不多说 上来就是一个test测试一下会不会变化 可以看到提示信息有输入的内容 昨天我想了一个可以看到JS变化的代码 话不多说直接上
  • Navicat 链接 MongoDB

    安装完毕后修改配置文件 vim etc mongod conf 默认127 0 0 1为只允许本地连接 0 0 0 0为不限制 多个指定服务器用 连接 bind ip 0 0 0 0 启动 mongod 启动命令行 gt systemctl
  • Android关于libs,jniLibs库的基本使用说明及冲突解决

    最近在开发中遇到了一个问题 因为项目需要集成不同的sdk 相对应的也是不同的 so文件 针对libs中 so库的引入会遇到一些问题 比如要集成第三方NDK库 如果是在eclipse中 需要放到libs下对应库的目录 如果是在Android
  • OpenCV人脸识别C++源码分析

    include cv h include highgui h include