完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
0. 目的
对RK3单板_IN输入摄像头)进行人脸识别(类似RK3的识别结果进行模糊化处理。 1. 智能环境 1.1 安装Android Studio 我下的是这个android-studio-ide-201.6953283-linux.tar.gz,下载地址找不到了。 1.2 下载TengineKit Github源码链接 git 克隆 https://github.com/OAID/TengineKit.git 1.3 设置AndroidStudio环境 · 第一个比较坑的就是gradle的同步地址要更新以下,可参考。 ·第二个就是设置SDK,我用的是安卓7.1,文件---设置---外观...---Android SDK设置如下: · build.gradle设置如下:(按说targetSdkVersion应该是25才对,但不知道为什么28也可以,有空再搞清楚这几个SdkVersion的关系) 2. TengineKit Demo项目结构 整个项目文件结果变成图。水平有限说不出来个啥。 CameraEngine.java 根据前后摄像头的配置设置了就是下面摄像头的旋转角度,但是因为 RK3399 的 HDMI_IN 比较特殊,虽然摄像头 id 为 0(面向背面)但是感觉这个面向背面传递小于背面的中。 ConnectionFragment.java 里好象下面,方法了受保护的选择OptimalSize)作用可以根据设置的最宽的相机预期尺寸就是最好的这个长度比。 改的最多的是Fragment和Classifier Activity,主要功能是“完成Camera所支持的两个Camera Connection”的预期图像功能、完成和配置“Camera的预视图、方向申请预览、Legacyera的缓冲区”等之前主要是调用TengineKit的jar(aar)包、根据人脸数据对图像进行模糊处理等。 utils下是图像类的一些处理方法,如高斯模糊等。 3.问题及解决 个人的输出预测:TengineKit在设计初是为了手机(竖屏)使用的,默认构建出来的版本,因此的图像是顺时针旋转了90°的,: RK3399 终端的屏幕是横屏的关系) 我们是一个横屏的所有旋转画面的表情都可以输入。那只是老实实实地的下沉心来学习。。。。 最终有以下几个认定点: 1. TengineKit 的图像有角度限制,否则识别率很低。对于0°横置的后置相机设备,TengineKit 的输出(主要说是faceLandmarks.get(i).BoundingBox(get)返回的矩形)的位置)是“平面镜后、顺时针转90°、并作宽高比调整后”的结果。 2. 对Bitmap的后处理需要根据TengineKit的行为做一些逆向Kit的标记。如我们针输出到Tengine的输出(faceLands.get(i).getBoundingBox()方法返回的Rect)后,需要转90° (与宽高比转换一起完成),然后再做一个水平镜的处理得到我们正确的结果。 根据这两个代码的发现,一共修改了 LegacyCameraConnectionFragment.java 和 ClassifierActivity.java 两个文件。如下: LegacyCameraConnectionFragment.java 公共无效 onSurfaceTextureAvailable(最终 SurfaceTexture 纹理,最终 int 宽度,最终 int 高度){ …… …… // camera.setDisplayOrientation(90); // 原版的 camera.setDisplayOrientation(0); // 更新 …… …… // camera.addCallbackBuffer(new byte[ImageUtils.getYUVByteSize(s.height, s.width)]); // 原版的 // textureView.setAspectRatio(s.height, s.width); // 原版的 camera.addCallbackBuffer(new byte[ImageUtils.getYUVByteSize(s.width, s.height)]);// 更新 textureView.setAspectRatio(s.width, s.height); //更新 camera.startPreview(); } ClassifierActivity.java 公共无效drawCallback(最终画布画布){ 如果(测试位图!= null){ canvas.drawBitmap(testBitmap, 0,0, circlePaint); } 如果(人脸地标!= null){ for (int i = 0; i < faceLandmarks.size(); i++) { 矩形 r = Transform_anticlock_90deg(faceLandmarks.get(i).getBoundingBox(), outputWidth, outputHeight); // 更新 // 矩形 r = faceLandmarks.get(i).getBoundingBox(); // 原版的 canvas.drawRect(r, circlePaint); canvas.drawBitmap(testFaceBitmaps.get(i), r.left, r.top, circlePaint); } } } protected void processImage(byte[] data, int previewWidth, int previewHeight, int outputWidth, int outputHeight) { ………… …… 如果(测试位图!= null){ testBitmap.recycle(); } testBitmap = Face.Image.convertCameraYUVData( 数据, 预览宽度,预览高度, 输出宽度,输出高度, // - 90, // 原始 // 真的); // 原版的 0, // 更新 错误的); // 更新 矩形 tmpRect = 新矩形(0,1,0,1);// 添加,临时变量,可不要。 if(testBitmap != null && faceDetect.getFaceCount() > 0){ 如果(人脸地标!= null){ for (int i = 0; i < faceLandmarks.size(); i++) { tmpRect = Transform_anticlock_90deg(faceLandmarks.get(i).getBoundingBox(),outputWidth,outputHeight); //添加 位图面 = BitmapUtils.getDstArea(testBitmap, tmpRect); //添加 // 位图 face = BitmapUtils.getDstArea(testBitmap, faceLandmarks.get(i).getBoundingBox()); face = BitmapUtils.blurByGauss(face, 50); testFaceBitmaps.add(face); } } } …… …… } //下面为新增代码。坐标原点(0,0)在左上角显示,区域在第四象限 public Rect Transform_anticlock_90deg(Rect inRect, int view_width, int view_height) // 逆时针转90°并水平镜像 { 矩形 outRect = new Rect(0,10,0,10); 最终浮动 h_to_w_ratio = (float)view_height/(float)view_width; 最终整数 x0,y0,x1,y1,newX0,newY0,newX1,newY1; x0 = inRect.left; // 不需要x0 y0 = inRect.top; x1 = inRect.left + inRect.width(); y1 = inRect.top + inRect.height(); //计算逆时针转90°后的坐标(含宽高比转换) newX0 = (int)((float)y0 / h_to_w_ratio); newY0 = (int)((float)(view_width - x1) * h_to_w_ratio); newX1 = (int)((float)y1 / h_to_w_ratio); newY1 = (int)((float)inRect.width() * h_to_w_ratio) + newY0; //生成旋转后的Rect outRect.set(newX0,newY0,newX1,newY1); // 镜像 outRect.set(RectMirror(outRect,view_width,view_height,true)); 返回输出矩形; } private Rect RectMirror(Rect inRect, int view_width, int view_height, boolean isHorizontal) // 镜像镜像 { 矩形 outRect = new Rect(); if (isHzontal == true) { //水平镜像 outRect.set(view_width - inRect.right, inRect.top, view_width - inRect.left, inRect.bottom); } else { // 对称 outRect.set(inRect.left, view_height-inRect.bottom, inRect.right, view_height-inRect.top); } 返回输出矩形; } 额外修改显示的画面大小的区域ClassfierActivity.java里 受保护的大小 getDesiredPreviewFrameSize() { 返回新尺寸(1920、1080);//我的片源是1080p的,如果改小了会显示不全,还是对相机玩得不熟。 } 以后旋转的图像就正确了。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
465 浏览 0 评论
475 浏览 0 评论
961 浏览 1 评论
【幸狐Omni3576边缘计算套件试用体验】自行转换大模型失败,搞一个语音小智玩玩吧.
475 浏览 1 评论
【幸狐Omni3576边缘计算套件试用体验】使用rkllm运行DeepSeek的服务模式体验
883 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-4-4 19:13 , Processed in 0.332177 second(s), Total 37, Slave 32 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191