华为北京研究所第一届黑客马拉松比赛-基于Android防止儿童走失

2022万向区块链春季黑客马拉松赛题及奖励详解 2022万向区块链春季黑客马拉松正在全球火热招募中!本次大赛由万向区块链实验室主办,Nervos、Protocol Labs和Qtum(按首字母音序排列)倾情赞助,北京大学学生区块链中心、北京航空航天大学区块链协会、北京邮电大学区块链协会、复旦MBA区块链俱乐部、上海交通大学区块链协会、清华大学学生区块链协会、Yale Venture Club及以太行星(按首字母音序排列)提供社区支持。 本次大赛以“元宇宙:一起链未来”为主题,鼓励全新项目和创意参赛,期待参赛者从DID、DAO、NFT、SocialF 阅读详情

简介

  这个项目是在2016年华为研究所举办的第一届黑客马拉松比赛时开发的项目,这个项目是借鉴之前写Android人脸对比,想出一个关于防止儿童走失的想法,然后增加浏览历史和定位失踪儿童以及推送附近人的功能。
  其实整个项目并不难,并且也很粗糙,但是由于整个项目从开始到结束都是我一个人开发,尤其到最后决赛的极限4小时编程,那种紧张、压抑的气氛充斥着整个赛场,还好在最后一刻完成了发布的任务,在最后的决赛中获得了第二的成绩(与第一名仅差了0.3分),对于这个成绩我还是比较满意的,在这里我要感谢一下我的其他两位队友(下面的效果图就是其中一位),都是北大的才子。

  首先看一下效果图,第一个gif是发送丢失信息的功能演示;第二个gif是接收到推送,进行比对功能的演示。

这里写图片描述

这里写图片描述

一、基础知识


在这个项目中使用到了很多第三方的SDK,现在市场上有很多免费的第三方工具类SDK供大家使用,很多比较难使用的,需要配置很多参数,开发代码特别多,但是功能还不能保证。这次开发中在选择第三方工具类上就花费了很长的时间,综合评定后决定使用下面这几个第三方的SDK:

Face++

  Face++人脸识别的三个核心概念:Image,Face和FaceId。
  
  Image指用户或应用程序给Face++API提供的图片,以供后续检测/识别使用。用户可以通过制定的url或在程序中上传(通过HTTP POST提交图片的二进制文件)提供Image。

  Face指Image中检测出得人脸。一张Image中可能包含多个Face,但是在我写的Demo中只用到一个Face。
  FaceId指上传到Face++服务器后,服务器返回的人脸标示符,在后面的对比中可以直接使用FaceId进行对比。

 定位

  这里使用的高德定位的API,Android 定位 SDK 是一套简单的LBS服务定位接口,您可以使用这套定位API获取定位结果、逆地理编码(地址文字描述)、以及地理围栏功能。
  下面是简单的代码示例,具体的功能以及参数请参考官网。


//声明mLocationOption对象
public AMapLocationClientOption mLocationOption = null;
mlocationClient = new AMapLocationClient(this);
//初始化定位参数
mLocationOption = new AMapLocationClientOption();
//设置定位监听
mlocationClient.setLocationListener(this);
//设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
mLocationOption.setLocationMode(AMapLocationMode.Hight_Accuracy);
//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setInterval(2000);
//设置定位参数
mlocationClient.setLocationOption(mLocationOption);
// 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
// 注意设置合适的定位时间的间隔(最小间隔支持为2000ms),并且在合适时间调用stopLocation()方法来取消定位请求
// 在定位结束后,在合适的生命周期调用onDestroy()方法
// 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
//启动定位
mlocationClient.startLocation();
@Override
    public void onLocationChanged(AMapLocation amapLocation) {
        if (amapLocation != null) {
        if (amapLocation.getErrorCode() == 0) {
        //定位成功回调信息,设置相关消息
        amapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见定位类型表
        amapLocation.getLatitude();//获取纬度
        amapLocation.getLongitude();//获取经度
        amapLocation.getAccuracy();//获取精度信息
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date(amapLocation.getTime());
        df.format(date);//定位时间
    } else {
              //显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。
        Log.e("AmapError","location Error, ErrCode:"
            + amapLocation.getErrorCode() + ", errInfo:"
            + amapLocation.getErrorInfo());
        }
    }
    }

推送

  在这里我必须吐槽一下友盟推送和Bmob推送,这两个对于开发者来说太不友善了,使用起来太麻烦,而且还有很多bug。
  这里使用的推送是LeanCloud开发推送功能,总体而言还是比较简单的。开发文档清晰简洁,链接上面已经给出了。

属性动画

  属性动画这里使用的第三方的库:NineOldAndroids。NineOldAndroids是一个乡下兼容的动画库,主要的使低于API 11的系统也能够使用View的属性动画。以下是官网的描述:

Android library for using the Honeycomb (Android 3.0) animation API on all versions of the platform back to 1.0!Animation prior to Honeycomb was very limited in what it could accomplish so in Android 3.x a new API was written. With only a change in imports, we are able to use a large subset of the new-style animation with exactly the same API.

  View的属性动画在Android API 11及其以后才支持,该库的作用就是让API 11以下的系统也能够正常的使用属性动画。它的雷鸣、用法与官方都一样,只是包名不一样。使用该库,你就可以在API版本很低的情况下也能够使用各种属性动画,让你的应用更加有动感、平滑。官方地址:NineOldAndroids。

EventBus

  EventBus指的是一个发布/订阅的时间总线,EventBus包含4个成分:发布者,订阅者,事件,总线。4者之间的关系大体如下:

这里写图片描述

  订阅者可以订阅多个事件,发送者可以发布任何事件,发布者同时也可以是订阅者。使用EventBus的优点是:独立出一个发布订阅模块,调用者可以通过使用这个模块,屏蔽一些线程切换的问题,简单地实现发布订阅功能。另个一优点是解耦合,是类之间的耦合降低。

  xUtils的BitmapUtils,它替我们考虑所有图片加载的情况,大体来说就是使用了三级缓存来加载网络图片和本地图片,让我们的程序不会因为图片造成内存溢出的BUG。

二、项目流程


  整个项目是分为两个大的功能部分:寻找家人和我是志愿者。

寻找家人

  这个模块主要是发送丢失儿童的信息,使用到推送和定位,整个发送的步骤主要是以下几步:
  1、上传丢失儿童的照片信息。
  2、选择是否需要将此条信息推送到周围人。
  3、进入到推送成功的页面。

志愿者

  这个模块也是整个项目的核心部分人脸对比,下面是对比的具体步骤:

  ps:四张作为对比样本的图片,是从网络下载的。
  1、首先选取一张照片(从手机相册或者拍摄得到),然后点击开始比对。
  2、使用FaceDetecter(线上或者离线)API分析bitmap,将探测到的人脸存储到Face中。
  3、根据Face中的数据,将人脸部分提取出来,然后逐一跟之前的四张图片进行对比。
  4、将对比的结果显示出来。

三、要代码分析


主要代码分析

因为整个项目都是围绕着人脸识别展开的,那FacePlusPlusHelper肯定是最重要的,我把Face++的API中的几个我使用的方法封装的这个类中。

/**
 * Created by Android Studio. author: liyachao Date: 2016/11/7 Time: 14:32
 */
public class FacePlusPlusHelper {
    private static final String TAG = "FacePlusPlusHelper";
    /**
     * 这里最好换成自己的apikey和apiSecret
     */
    private static final String apiKey = "000feb0633099eb6167e7ad3270b5338";
    private static final String apiSecret = "HL9WV4BOrBJ-8LSgsyDAHXgJUtezgJxN";

    public static final int METHOD_ONE = 50001;
    public static final int METHOD_TWO = 50002;
    public static final int METHOD_THREE = 50003;

    private FaceDetecter detecter;
    private Context context;
    private Handler detectHandler;
    private HandlerThread detectThread;

    HttpRequests httpRequests;

    private static class FacePlusPlusHelperHolder {
        private static FacePlusPlusHelper facePlusPlusHelper = new FacePlusPlusHelper(MyApplication.getContextObject());
    }


    public static FacePlusPlusHelper getInstance() {
        return FacePlusPlusHelperHolder.facePlusPlusHelper;
    }

    private FacePlusPlusHelper(Context context) {
        this.context = context;

        detectThread = new HandlerThread("detect");
        detectThread.start();
        detectHandler = new Handler(detectThread.getLooper());

        httpRequests = new HttpRequests(apiKey, apiSecret, true, false);
        httpRequests.setHttpTimeOut(60000);
        if (!MyUtils.isCPUInfo64()) {
            detecter = new FaceDetecter();
            detecter.init(context, apiKey);
        }

    }

    public void stopThread() {
        detectHandler.removeCallbacksAndMessages(null);
    }


    /**
     * 探测选取的图片是否有脸
     */
    public void faceDetect(final String url) {
        final EventBean bean = new EventBean();
        detectHandler.post(new Runnable() {
            @Override
            public void run() {
//                if (detecter == null) {
                try {
                    JSONObject rst;
                    PostParameters parameters = new PostParameters();
                    if (url.startsWith("http")) {
                        parameters.setUrl(url);
                    } else {
                        Bitmap bitmap = MyUtils.getScaledBitmap(url);
                        byte[] bytes = MyUtils.bitmapToBytes(bitmap);
                        parameters.setImg(bytes);
                    }
                    rst = httpRequests.detectionDetect(parameters);

                    try {
                        int count = rst.getJSONArray("face").length();
                        if (count == 0) {
                            bean.setIsCorrect(false);
                            bean.setMode(METHOD_ONE);
                            bean.setDescribe("没有探测到脸,请再次选择或者拍摄");
                            EventBus.getDefault().post(bean);
                        } else {
                            float x = (float) rst.getJSONArray("face").getJSONObject(0)
                                    .getJSONObject("position").getJSONObject("center").getDouble("x");
                            float y = (float) rst.getJSONArray("face").getJSONObject(0)
                                    .getJSONObject("position").getJSONObject("center").getDouble("y");
                            //get face size
                            float w = (float) rst.getJSONArray("face").getJSONObject(0)
                                    .getJSONObject("position").getDouble("width") * 0.5f;
                            float h = (float) rst.getJSONArray("face").getJSONObject(0)
                                    .getJSONObject("position").getDouble("height") * 0.5f;
                            String detectFaceId = rst.getJSONArray("face").getJSONObject(0)
                                    .getString("face_id");

                            Face face = new Face();
                            face.left = (x - w) / 100f;
                            face.right = (x + w) / 100f;
                            face.top = (y - h) / 100f;
                            face.bottom = (y + h) / 100f;
                            bean.setIsCorrect(true);
                            bean.setFace(face);
                            bean.setMode(METHOD_ONE);

                            bean.setFaceId(detectFaceId);

                            Log.i("AVInstallation", "url1: " + url);
                            if (url.startsWith("http")) {
                                bean.setImage(url);
                                EventBus.getDefault().post(bean);
                            } else {
                                try {
                                    final AVFile avFile = AVFile.withAbsoluteLocalPath(url, url);
                                    avFile.saveInBackground(new SaveCallback() {
                                        @Override
                                        public void done(AVException e) {
                                            Log.i("AVInstallation", "e: " + (e != null ? e.toString() : null));
                                            bean.setImage(avFile.getUrl());

                                            Log.i("AVInstallation", "url2: " + bean.getImage());

                                            EventBus.getDefault().post(bean);
                                        }
                                    });
                                } catch (FileNotFoundException e) {
                                    Log.i("AVInstallation", "url2: fail");
                                    e.printStackTrace();
                                }
                            }


                        }
                    } catch (JSONException e) {
                        bean.setIsCorrect(false);
                        bean.setMode(METHOD_ONE);
                        bean.setDescribe("探测失败,请重新比对");
                        EventBus.getDefault().post(bean);
                        e.printStackTrace();
                    }
                } catch (FaceppParseException e) {
                    bean.setIsCorrect(false);
                    bean.setMode(METHOD_ONE);
                    bean.setDescribe("探测失败,请重新比对");
                    EventBus.getDefault().post(bean);
                    e.printStackTrace();
                }

            }
        });
    }




    /**
     * 对比两个图片中脸部的相似度
     *
     * @param faceId1 已经得到的Faceid
     */
    public void comparisonFace(final String faceId1, final String url, final String faceId2) {
        final EventBean bean = new EventBean();
        detectHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    String comFaceId = faceId2;

                    long timeStart = System.currentTimeMillis();
                    JSONObject rst;
                    PostParameters parameters = new PostParameters();
                    Log.i("liyachao3", "faceId1: " + faceId1 + "\n faceId2: " + faceId2);
                    if (comFaceId == null || comFaceId.length() == 0) {
                        if (url.startsWith("http")) {
                            parameters.setUrl(url);
                            rst = httpRequests.detectionDetect(parameters);
                        } else {
                            Bitmap bitmap = MyUtils.getScaledBitmap(url);
                            byte[] bytes = MyUtils.bitmapToBytes(bitmap);
                            parameters.setImg(bytes);
                            rst = httpRequests.detectionDetect(parameters);
                        }

                        int count = rst.getJSONArray("face").length();
                        if (count == 0) {
                            bean.setIsCorrect(false);
                            bean.setMode(METHOD_THREE);
                            bean.setDescribe("没有探测到脸,请重新拍照");
                            EventBus.getDefault().post(bean);
                        } else {
                            comFaceId = rst.getJSONArray("face").getJSONObject(0)
                                    .getString("face_id");
                            Log.i(TAG, "comparisonFace: " + rst.toString());
                        }
                    }
                    parameters = new PostParameters();
                    parameters.addAttribute("face_id1", faceId1);
                    parameters.addAttribute("face_id2", comFaceId);
                    JSONObject result = httpRequests
                            .recognitionCompare(parameters);
                    if (result == null || result.toString().equals("")) {
                        bean.setIsCorrect(false);
                        bean.setMode(METHOD_THREE);
                        EventBus.getDefault().post(bean);
                    } else {
                        double similarity = result.getDouble("similarity");
                        long timeEnd = System.currentTimeMillis();
                        if (timeEnd - timeStart < 2000) {
                            Thread.sleep(2000 - (timeEnd - timeStart));
                        }
                        bean.setIsCorrect(true);
                        bean.setDescribe(similarity + "");
                        bean.setMode(METHOD_THREE);
                        EventBus.getDefault().post(bean);
                    }

                } catch (Exception e) {
                    bean.setIsCorrect(false);
                    bean.setMode(METHOD_THREE);
                    bean.setDescribe("比对失败");
                    EventBus.getDefault().post(bean);
                    e.printStackTrace();
                }
            }
        });
    }


}

  首先提取一些需要用到的常量,因为整个类中主要有三个方法:探测脸部,请求FaceId,脸部对比,所以需要用三种类型代表不同的方法,方便在EventBus中做区分。
  代码初始化了一个线程,用来请求网络(因为请求网络是耗时的操作,因此需要开启线程,不能在UI线程中直接请求,否则会造成程序崩溃),初始化了FaceDetecter(Face++的离线包),大家可以看到我这里做了一个手机CPU是否为64位的判断,因为Face++离线包中没有做64位的so,所以如果手机64位的还直接调用Face++的离线包,会有Bug。如果手机是64位,则直接请求网络来探测脸部。
  剩下的方法都在程序中做了注释,大家应该可以看懂。
  大家可以看到,在请求网络成功时,我这里没有使用到回调,而是使用的EventBus,和回调是一个效果。

  剩下的代码,就不一一讲解了,项目中的代码不难,如果感兴趣的朋友可以和我讨论。

四、总结

  这个项目中运用到的知识点还是比较多的,很多地方都没有讲到,不过我相信对于大家来说,都应该能够看懂,如果有什么不清楚的地方,可以留言,互相讨论。
  如果其中有什么不对或者不足的地方,希望大家能提出来。

  如果大家觉得还可以,请给我点赞。

github下载地址

优快云下载地址

【论文泛读|附源码】如何进行动力学重构? 神经网络自动编码器结合SINDy发现数据背后蕴含的方程 这一篇文章叫做 **数据驱动**的**坐标发现与方程发现算法**。想回答的问题很简单,就是根据数据写方程。 想想牛顿的处境,如何根据各种不同物体下落的数据,写出万有引力的数学公式的。这篇文章就是来做这件事的。当然,这篇论文并没有从牛顿视角,完全去思考牛顿所想。而是利用现有的**深度学习技术** 和 **动力学重构的方法** 。提出了一种框架,基于现有的计算机技术,去发现物质运动背后的物理规律。 这里直接给出这篇方法的核心思路图,我们后面会逐个讲解。 阅读详情

相关推荐

ESP32S3电池电量监测实战:从分压电路到IDF组件配置(附GitHub源码)

本文详细介绍了ESP32S3电池电量监测的完整实战方案。从硬件分压电路的电阻选型、滤波设计,到软件层面利用ESP-IDF的ADC校准机制提升精度,并重点讲解了如何集成bat_monitor开源组件快速实现电压采集、电量计算、充电检测与事件通知。文章提供了从原理到调试的完整指南和GitHub源码,帮助开发者构建稳定可靠的物联网设备电源管理系统。

ee345的博客 529

2024华为软件精英挑战赛记录

2024年华为软件挑战赛记录。

m0_49586319的博客 3588

从“氛围编程“到“智能体工程“:AI编程范式的认知跃迁与工程实践

摘要: 2026年,ClaudeCode负责人鲍里斯·切尔尼提出用“智能体工程”(Agent Engineering)替代流行的“氛围编程”(Vibe Coding),认为后者过于主观,无法体现AI编程的系统化与工程化本质。智能体工程强调记忆系统、工具编排、任务分解、可观测性等核心技术,将AI编程从“玄学辅助”升级为可度量、可规模化的工程学科。本文通过对比术语差异、构建知识体系,并结合代码实例(如带记忆系统的代码生成Agent和可观测性系统),展示了智能体工程的实际应用。行业案例(如ClaudeCode的并

yyq916的博客 1060

【DevOps黑客马拉松挑战赛—大连站】

IDCF DevOps黑客马拉松: “打造端到端的DevOps人才”! “在36小时内从0到1打造并发布一款产品!” DevOps实践与敏捷开发正在席卷IT公司,精益创业、设计思维、增长黑客等硅谷创新思维与方法,正在被越来越多具有真知灼见的企业接受并实践。研究显示,在那些引入了DevOps方法的企业中,精英效能组织对比低效能组织,在部署频率、部署前置时间、变更失败率、故障恢复时间等关键指标上,有7倍到2604倍的差距。 在内容设计上,DevOps黑客马拉松融合了最新的硅谷创新与研发理念,贯穿设计

m0_69584846的博客 449

别再只跑memtester了!嵌入式Linux内存压力测试,这5个参数和场景你试过吗?

本文深入探讨了嵌入式Linux内存压力测试的高级技巧,重点解析了memtester工具的5个关键参数和实战场景。通过物理地址测试、迭代控制、内存分配策略等调优方法,帮助开发者有效检测内存稳定性问题,适用于长期运行设备、特定故障重现等复杂场景,提升嵌入式系统可靠性。

weixin_30838873的博客 424

UG/NX二次开发Siemens官方NXOPEN实例解析—1.3 BlockStyler/ExtrudewithPreview

随着工业智能化的不断发展,UG二次开发的需求越来越多,也吸引了大批的二开从业人员,本人作为一名资深IT从业者(10年+)也毅然加入二次开发大军。然而,和流行IT行业(互联网、金融、医疗等)相比,工业智能化的门槛显得更高一点,专业的工业软件,相对封闭的开发理念和更小的开发圈子,让刚进入二开的从业者有点举步维艰。边学边整理,希望通过这系列文章的整理能给二开的生态增添一叶绿。

MarcoPro的博客 1632

赛场直击:万向黑客马拉松Qtum题目全解析

回顾:Qtum量子链应邀参加2018万向区块链黑客马拉松近日,Qtum量子链应邀出席参加万向区块链黑客马拉松,其中Qtum核心开发工程师郑翊作为评委向在场的各位开发者出两道区块链技术题目,并且在场开出10000美金的奖赏作为对优秀团队的奖励。QtumSwap团队赢得了本场活动的重金悬赏,那么他们是如何解开题目呢?首先,我们先来看看题目是什么?测试网水龙头其中我们要求开发者设计一个测试网的水龙头,其...

weixin_33868027的博客 678

【电驱动】永磁同步电机工作原理及分类

永磁同步电机工作原理及分类

星Yeah 的博客 7321

自我黑客马拉松 -- 从零开始创建一个基于Go语言的web service

20个小时的时间能干什么?也许浑浑噩噩就过去了,也许能看一些书、做一些工作、读几篇博客、再写个一两篇博客,等等。而黑客马拉松(HackAthon),其实是一种自我挑战--看看自己在有限的短时间内究竟能做出些什么。比如:让一个毫无某种语言经验的人用该种语言去实现4个如下的Restful API(假设此种语言为Go)。

FinixLei的专栏 (https://github.com/FinixLei) 7829

Ubuntu下OpenOCD+GDB的安装、编译及使用

目标开发板(芯片):stm32mp157aaa 仿真器:ST-Link 操作系统:Ubuntu 18.04 调试软件:OpenOCD OpenOCD的安装 首先下载OpenOCD有多种方式,可以GitHub上下载,目录下打开终端,输入 git clone git://git.code.sf.net/p/openocd/code openocd 下载完整的OpenOCD的文件夹。进入到OpenOCD的目录下,开始安装。 接着,OpenOCD适用于微处理器的debug和烧写,需要下载相关库 sud

蓝冰露的博客 9524

使用 syncstart 实现同场景下多个音视频音轨自动化同步

如果需要在视频编辑中同步多个机位的音轨,使得相同的视频能够同时播放,手动操作可能会变得相当复杂。特别是当处理多个视频文件时,例如有10个视频需要互相匹配,实现一对多的同步关系,这就涉及到为每对视频生成匹配的音轨数据。手动完成这样的任务,如生成90套对应的音轨数据,不仅耗时而且容易出错。因此,使用脚本自动化这一过程是一个更为高效和准确的解决方案。通过编写脚本,您可以批量处理多个视频文件,自动同步它们的音轨,大大简化了音视频编辑的工作流程,并确保了同步的准确性。

Mr数据杨 1074

黑客马拉松题目_举办黑客马拉松的提示

黑客马拉松 招募 当您合并一家全球金融服务,媒体和数据公司时,您会得到什么呢?该公司雇用了5,000名软件开发人员,而这些软件开发人员的创始人都是慈善事业的创始人。 如果您是Bloomberg ,那么您将获得一系列公司赞助的黑客马拉松,员工,社区成员,学生和其他人员在一个周末聚会在一起,以利用开放源代码工具(包括Python,Perl和Eclipse)进行黑客攻击。 彭博社开放源代码项目...

cumo3681的博客 438

08 RK3568 MAC TO MAC直连 RTL8367S mdio

本文:采用rk3568 gamc0 通过rgmii直连 交换芯片的mac口 通信方法为mdio。

qq_39451352的博客 3473

总奖励已超38万,2021万向区块链黑客松赛题及奖励详解!

自8月3日正式开赛以来,2021万向区块链黑客马拉松的赛题不断升级、奖励持续加码!由主办方万向区块链实验室及Protocol Labs、Web3基金会、Qtum、Moonbean四位赞助商提供的总奖励已超38万人民币。冠军团队还将获得万向峰会主会场演讲机会,在全球区块链行业内提升团队及项目知名度。 参赛选手及团队可以通过同一个项目同时挑战大赛主命题和赞助商命题,向多份奖励和奖金发起冲击。 为帮助有意参赛的个人和团队开发者更好地了解本次大赛,小万特意对主办方及赞助商提供的赛题、奖励及项目要求做了全面梳理,

WXblockchain1的博客 2564

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

WeGeek 微信小程序黑客马拉松主题公布!

12 月 15 日-12 月 16 日,由腾讯公司微信事业群主办的「WeGeek 微信小程序黑客马拉松」将在北京正式启动,Hackathon 面向全球小程序开发者、爱好者,旨在通过微信小程序平台进行小程序的创新开发,共同建设小程序生态。 Hackathon 一经发布备受圈内外关注,报名通道开启两周内即有近 500 人报名,通过先后两轮筛选...

weixin_34275734的博客 313

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

SegmentFault Hackthon 2015 记录

We Came, We Saw, We Hacked 上周末(2015.10.24),我们参加了由 segmentfault 组织的亚洲最大规模的黑客马拉松。这次的Hackathon在 北京 / 杭州 / 深圳 / 济南 / 武汉 多城同时联动。仅我们参加的北京赛区,就有30多个团队,150余人。 本次赛事采用全新命题制,北京赛区的题...

weixin_34232617的博客 323

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Hack Money!!! 30天的虚拟黑客马拉松,专为世界各地的黑客构建Defi应用程序而设计,快来加入我们!

Hack Money!!! 30天的虚拟黑客马拉松,专为世界各地的黑客构建Defi应用程序而设计,快来加入我们! 为什么是虚拟的? ETHGlobal已经在世界各地组织了多达14场面对面的黑客大会以加速以太坊生态系统的发展。在此过程中,超过10,000名热诚的开发人员申请加入我们的活动,250个项目已经建成。今年早些时候,我们采访了这一领域的数十家公司以及黑客们,了解到他们希...

ETHPlanet的博客 732

有一份华为荣誉证书等你来拿!网络人工智能硬盘异常预测黑客松比赛火热报名中...

数据丢失对于企业来说是致命性问题储存数据的硬盘经常出现异常告警对于工程师来说也是头疼难题如何提升告警的实时性如何提高处理异常的速率算法即服务选好平台工具往往能事半功倍HDC2020华为...

Datawhale 2884

AngelHack2018全球黑客马拉松系列 - 上海站

戳这里抢早鸟票 全球最大的黑客马拉松带着价值100,000人民币的大奖来上海了! 今年AngelHack全球黑客马拉松系列首次登陆上海, 我们为大家带来了总价值约100,000人民币的奖励, 可口的美食零食饮料, 有趣的参赛伙伴, 以及难忘的参赛经历. AngelHack2018宣传视频 - Anyone can code 空想一整年, 不如实实在在干一个周末! 如果你有新奇有趣的想法, 或...

weixin_34384681的博客 883

2019 MiiX 全球黑客马拉松超级大赛招募

点击下方 阅读原文 即可报名!

Go中国 1476

Android OpenGL使用GLSurfaceView预览视频

前言一年之前做过一些即时通信视频相关的工作,主要是做视频渲染这一部分的工作,由于2016毕业来到了华为,华为对研究生的安排就是“哪里需要去哪里”,和你专业和擅长的没有太大的关系,所以一直在适应当下的工作,现在基本上可以胜任现在的工作,可以抽出一些时间来总结一下之前了解过的OpenGL相关知识。第一章 相关知识介绍在介绍具体的功能之前,先对一些主要的类和方法进行一些介绍,这样可以更好的理解整个程序1.

K-night的专栏 2万+

Android OpenGL渲染双视频

前言想做的有很多,奈何能力实在有限,所以只能一步一步来,将自己做出来的尽量用简单易懂的语言描述出来,希望自己总结的对阅读这篇文章的同学有所帮助。在上一篇文章中讲述了怎样在GLSurfaceView上预览Camera的视频数据,在本章中打算实现一个类似微信视频通话的效果,微信视频通话主要有大小两个视频数据渲染(自己的视频和对端的视频),手指点击小视频,可以切换大视频和小视频的位置,可以拖动小视频。第一

K-night的专栏 9801

初识Android OpenGL ES

第一章 创建OpenGL ES的环境首先需要为OpenGL ES创建一个视图(View)容器,一种实现方式是创建一个类实现GLSurfaceView和GLSurfaceView.Renderer。GLSurfaceView是显示图形的视图(View)容器,GLSurfaceView.Renderer是控制画图的方法。更多的介绍可以看OpenGL ES的开发指南。GLSurfaceView是多种集成O

K-night的专栏 4061

GLSL基础

OpenGL Shading Language GLSL作为一种着色语言是纯粹的和GPU打交道的计算机语言。因为GPU是多线程并行处理器,所以GLSL直接面向SIMD模型的多线程计算。GLSL编写的着色器函数是对每个数据同时执行的。每个顶点都会由顶点着色器中的算法处理,每个像素也都会由片段着色器中的算法处理。因此,初学者在编写自己的着色器时,需要考虑到SIMD的并发特定,并用并行计算的思路来思考问题

K-night的专栏 1589

Android 14+ 模拟器抓包实录:把 Burp CA 装成系统 CA,让 targetSdk≥34 的 App 乖乖解密

本文记录了在 Android 14+ 环境下,通过将 Burp CA 安装为系统信任锚,成功抓取 targetSdk=35 App 的 HTTPS 明文流量的完整实操过程。针对“浏览器可用、App 不可用”的典型现象,精准识别出根本原因是系统级证书信任策略变更(用户安装的 CA 被屏蔽),而非 SSL Pinning。仅通过 adb 命令将 CA 推送至系统证书存储并重启生效,无需 Frida、Objection 或修改 APK,实现零侵入解密。全文命令均基于 Windows + MuMu 模拟器环境实测通

JIANqiao19931029的博客 336

具身智能 2026:启元人形机器人开发者生态的“安卓时刻”来了吗

一个贯穿全文的问题:人形机器人开发者生态,是否正从「封闭垂直」走向「开源平台化」?本文以开源底座的公开数据为标尺,盘点 SDK、URDF、仿真与技能分发的开放程度,并落回启元机器人的开源路径。所有关键数据均标注来源,文末附社区与学堂链接。

在北风吹起的时候加入我们的队伍 在秋雨到来的时候成为彼此的温暖 722
上一篇: Android OpenGL渲染双视频
下一篇: 一年Android工作经验,今日头条 阿里 百度 网易 美团 小米 快手面经
Bobby_lyc
博客等级 码龄16年 1164粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值