多点触摸处理

Android触摸事件处理:单点触摸和多点触摸的区分与冲突解决 Android设备支持单点触摸和多点触摸,开发者需要准确地识别触摸事件的类型并解决可能出现的单点触摸和多点触摸的冲突。本文将介绍如何区分单点触摸和多点触摸,并提供相应的代码示例来解决单点触摸和多点触摸的冲突。例如,当用户用一个手指按下屏幕并保持不动时,另一个手指按下屏幕,此时会触发一个单点触摸事件和一个多点触摸事件。综上所述,我们可以通过区分单点触摸和多点触摸事件,并采取相应的处理策略来解决单点触摸和多点触摸的冲突。方法获取当前触摸屏幕的手指数量,我们可以在单点触摸事件中检测是否存在其他手指的触摸。 阅读详情

接着上文,我们做了一个简陋的下拉刷新控件,目前用到的知识点有

  1. view的滑动
  2. view的弹性滑动
  3. 事件分发机制
  4. 事件分发机制的两个小问题(事件的二次分发)

目前这个控件除了简陋一点,没做抽象封装,在单手操作下,表现还是不错的,但是多手操作试一下,页面会产生位移突变。这就引出了本节的多点触摸知识点

多点触摸的原理明白后,一般只是用来处理多点触摸所引起的bug,一般不会使用多点触摸来处理缩放等高级的多点触摸问题,因为毕竟太麻烦了,我们有系统封装好的GestureDetector、ScaleGestureDetector、GestureDetector.SimpleOnGestureListener

首先推荐这个大神的博客
安卓自定义View进阶-MotionEvent详解
安卓自定义View进阶-多点触控详解
以及这个官方教程
拖拽与缩放

知识点

前奏开始了

假设大家已经认真阅读了上边的博客,下面列出必知必会的知识点:

  1. 多点触控获取事件类型请使用 getActionMasked()

  2. 每一根手指有两个标记,index和pointId,

    index会随着之前手指的抬起而发生变化,pointId不会发生变化

  3. 说一下多指触摸下的事件流

    第一根手指按下:ACTION_DOWN(0x00000000)
    第二根手指按下:ACTION_POINTER_DOWN(0x00000105)
    第三根手指按下:ACTION_POINTER_DOWN(0x00000205)
    任意一根手指滑动:ACTION_MOVE(0x00000002)
    第三根手指抬起:ACTION_POINTER_UP(0x00000206)
    第二根手指抬起:ACTION_POINTER_UP(0x00000106)
    第一根手指抬起:ACTION_UP(0x00000001)

    只有第一根手指按下会调用ACTION_DOWN,其余手指按下,会调用ACTION_POINTER_DOWN,而且ACTION_POINTER_DOWN最后的105,5代表事件的类型(多指按下事件),那个1是该手指的index,同理205中的2代表第二根手指的index。

    当手指move时候,没有对应的事件类型,表明你在move哪根手指,都用(0x00000002)表示

    当最后一根手指抬起时,才会触发ACTION_UP,其余手指抬起来,触发的是ACTION_POINTER_UP,事件类型为6,前面的是手指index

  4. 重要的api
    盗图了,来自安卓自定义View进阶-MotionEvent详解
    在这里插入图片描述

 // 获取index,在move时候,此方法无效,只能在ACTION_DOWN,
 // ACTION_POINTER_DOWN,ACTION_POINTER_UP,
 // ACTION_UP里得到的index才是有效的
 int action_index = event.getActionIndex();
 // 通过index得到该手指的id
 int action_id = event.getPointerId(action_index);
 // 得到事件类型
 int action = event.getActionMasked();
 // 得到指定索引手指的y坐标
 float y = event.getY(activeIndex);

这才是最难理解的

关于多指操作时候,每一根手指的index和id的变化情况
我这里通过log来演示,log不包含move的情况,因为move不区分手指的index和id

在这里插入图片描述

  1. 前三步很好理解,依次按下三根手指,index和id依次递增(注意第三根手指index为2,id为2)
  2. 第四步抬起了第二根手指,index和id均显示1,也很正常
  3. 第五步按下第四根手指(重点1),index和id均显示1,【他填补了第二根手指释放的的index和id】
  4. 第六步,抬起第一根手指,index和id均显示0,也算正常
  5. 第七步,抬起第三根手指(重点2),index为1,id为2,但是当第三根手指按下时,index为2,id为2,【发现index变了,但是id没变】
  6. 第八步,抬起第四根手指,index为0,id为1,但是当第四根手指按下时,index为1,id为1,【同样发现index变了,但是id没变】

正是这种看似很奇怪的现象,导致我们追踪每一根手指的行为变得比较困难
观察log得出的结论是:
要想追踪手指,必须跟踪id,index会随着其他手指的抬起发生变化

这种变化,应该是,每次抬起一根手指,所有的手指的index中,比这根抬起的手指index大的都减去一,比他小的保持不变

应用:

如何跟踪指定的一根手指,无论其他手指如何起起落落,我都要追踪某一根手指。

大概思路:

  1. 每次down或ACTION_POINTER_DOWN时,通过index=event.getActionIndex()得到该手指的index,然后通过id=event.getPointerId(index)得到该手指的id,然后你记住这个id,存起来作比对用
  2. 然后现在要move了,你先得到手指数量count=event.getPointerCount(),再去遍历所有手指,此时遍历用到的是index,通过index得到id,看这个id是不是你要追踪的id,如果是的话,记住对应的index,然后通过y = event.getY(curActiveIndex)得到坐标信息,然后操作就行了
  3. 为什么上面,每次都是要找一次index,因为你不能直接通过event得到id和坐标值,必须通过index来得到,但是index又是不可靠的,老变化,不变的只有id,所以又要去比对id。

另一种思路,是每次当手指抬起时ACTION_POINTER_UP,去实时地算出你要追踪的手指的index。因为我们知道index小于抬起手指index的手指,index不变,大于的需要减去一,这样你可以准确地直接追踪index,再拿着index去都得到坐标,id就不用管了

回归到本例,如何解决位移突变问题

现象:

当一根手指下拉到一定位置时,另外一根手指按到屏幕上,然后松开第一根手指,发现,位移突变了

原因:

先看看这两个方法

float getY()

默认取index为0的手指的坐标
在这里插入图片描述

getY(int pointerIndex)

取出指定index的手指的坐标在这里插入图片描述

当我们一根手指下拉时(此刻这根手指的index为0),getY(),获取到的自然是这唯一的手指的坐标,
当第二根手指按住屏幕时(此刻这根手指的index为1),这根手指的Y坐标与之前的手指坐标里的较远,
此时第一根手指一松手,按照前面我们的分析,第二根手指的index马上变为0,那么getY,就会取到这个手指的坐标,然而他距离上一次的Y坐标离得很远了,所以deltaY=y-mLastY,deltaY会很大,导致位移突变

如何解决呢?

解决思路肯定是多点触摸了,但是你要解决城什么样子呢?拿出你的手机,随便翻出一个ScrollView或者RecyclerView,你多指触摸,仔细看看,发现系统的View处理原则是:

  1. 第一根手指按下滑动,页面响应滑动事件
  2. 第二根手指按下滑动时,页面响应滑动事件,但是此时第一根手指滑动不会导致页面滑动
  3. 第三根手指按下滑动时,页面响应滑动事件,但是此时第一根和第二根手指滑动都不会导致页面滑动
  4. 第四根手指按下滑动时,页面响应滑动事件,但是此时第一根、第二根和第三根手指滑动都不会导致页面滑动
    结论:在多根手指依次按到页面上时,追踪的是最新的那根手指的滑动事件
  5. 现在页面上有四根手指,松开第三根手指,发现,依然第四根手指控制滑动,其余的手指滑动无效
  6. 现在页面上有三根手指,松开第四根手指(也就是当前控制滑动的手指),发现,第一根手指控制滑动,其余的手指滑动无效
  7. 结论:在多根手指按到页面上时,如果松开的是非操控手指,那么操控权依然是刚才的操控手指,如果松开的是当前的操控手指,那么把操控权,交给index为0的手指,即第一根手指

ok,我们就来实现以下,上面的多指触摸逻辑

代码

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

源码

package com.view.custom.dosometest.view;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ScrollView;

/**
 * 描述当前版本功能
 *
 * @Project: DoSomeTest
 * @author: cjx
 * @date: 2019-12-01 10:06  星期日
 */
public class RefreshView extends LinearLayout {


    private ScrollView mScrollView;
    private View mHeader;
    private int mHeaderHeight;
    private MarginLayoutParams mLp;

    public RefreshView(Context context) {
        super(context);
        init(context);
    }

    public RefreshView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public RefreshView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    private void init(Context context) {
        setBackgroundColor(Color.GRAY);

        post(new Runnable() {
            @Override
            public void run() {
                initView();// 因为涉及到获取控件宽高的问题,所以写到post里
            }
        });

    }

    private void initView() {

        if (getChildCount() > 2) {

            // 给刷新头设置负高度的margin,让他隐藏
            mHeader = getChildAt(0);
            mHeaderHeight = mHeader.getMeasuredHeight();
            mLp = (MarginLayoutParams) mHeader.getLayoutParams();
            mLp.topMargin = -mHeaderHeight;
            mHeader.setLayoutParams(mLp);

            // 得到第二个view,scrollView
            View child1 = getChildAt(1);
            if (child1 instanceof ScrollView) {
                mScrollView = (ScrollView) child1;
            }

        }
    }


    float mLastY;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        boolean intercept = false;
        int x = (int) ev.getX();
        int y = (int) ev.getY();

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                intercept = false;
                break;

            case MotionEvent.ACTION_MOVE:
                int deltaY = (int) (y - mLastY);
                if (needIntercept(deltaY)) {//外部拦截的模板代码,只要重写needIntercept方法逻辑就行
                    //注意当前ViewGroup一旦拦截,一次事件序列中就再也不会调用onInterceptTouchEvent了,
                    // 所以子View再也不会得到事件处理的机会了
                    // 为了解决这个问题,就引出了《嵌套滑动》这个新的事物,见下文
                    intercept = true;
                } else {
                    intercept = false;
                }

                break;

            case MotionEvent.ACTION_UP:

                intercept = false;

                break;
            default:
                break;
        }

        mLastY = y;
        return intercept;
    }

    private boolean needIntercept(int deltaInteceptY) {
        // mScrollView已经下拉到最顶部&&你还在下来,那么父容器拦截
        if (!mScrollView.canScrollVertically(-1) && deltaInteceptY > 0) {
            Log.e("ccc", "不能再往下拉了&&你还在往下拉,父布局拦截,开始拉出刷新头");
            return true;
        }
        if (mLp.topMargin > -mHeaderHeight) {
            Log.e("ccc", "只要顶部刷新头,显示着,就让父布局拦截");
            return true;
        }

        return false;
    }

    @Override
    public void requestDisallowInterceptTouchEvent(boolean b) {
        // 去掉默认行为,使得每个事件都会经过这个Layout
    }

    int curActiveId = 0;// 当前操作滑动的手指的id
    int lastActiveId = 0;//上次操作滑动的手指的id
    int curActiveIndex = 0;//当前操作滑动的手指的index

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int count = event.getPointerCount();
        // 避免索引越界,应该不会越界,判断一下稳妥
        curActiveIndex = (curActiveIndex >= count) ? count - 1 : curActiveIndex;
        curActiveIndex = (curActiveIndex < 0) ? 0 : curActiveIndex;
        Log.e("qqq", "curActiveIndex:" + curActiveIndex);
        float y = event.getY(curActiveIndex);//得到操控手指的坐标(只是关心操控手指)
        curActiveId = event.getPointerId(curActiveIndex);
        //下面判断手指是不是同一个,必须用id,因为index随时会变的
        if (curActiveId != lastActiveId) {//判断当前操控手指id和上次操控手指id是不是一样
            mLastY = y;//★★★如果不一样,马上把此刻的y坐标赋值给上次的y坐标,这是避免位移突变的关键点
        }

        switch (event.getActionMasked()) {//一定要用getActionMasked
            case MotionEvent.ACTION_DOWN:

                break;

            case MotionEvent.ACTION_POINTER_DOWN:
                //新手指按下,让它成为控制手指,更新下当前的控制手指的index
                curActiveIndex = event.getActionIndex();
                break;

            case MotionEvent.ACTION_POINTER_UP:

                int upIndex = event.getActionIndex();
                Log.e("qqq", "upIndex:" + upIndex + " curActiveIndex:" + curActiveIndex);
                if (curActiveIndex > upIndex) {
                    // 如果当前控制手指的index>抬起的手指index,需要减去一(很关键,博客分析过)
                    curActiveIndex = curActiveIndex - 1;
                } else if (curActiveIndex == upIndex) {
                    // 如果相等,说明你抬起来的就是操控手指,那么变更操控手指为第一根手指
                    curActiveIndex = 0;
                }

                break;


            case MotionEvent.ACTION_MOVE:
                float deltaY = y - mLastY;

                // 防止刷新头被无限制下拉,限定个高度

                if (mLp.topMargin + deltaY > mHeaderHeight) {
                    deltaY = mHeaderHeight - mLp.topMargin;
                }
                // 动态改变刷新头的topMargin
                mLp.topMargin += (int) deltaY;
                Log.e("ccc", "y:" + y + "mLastY:" + mLastY + "deltaY:" + deltaY + "mLp.topMargin:" + mLp.topMargin);
                mHeader.setLayoutParams(mLp);

                if (mLp.topMargin <= -mHeaderHeight && deltaY < 0) {
                    // 重新dispatch一次down事件,使得列表可以继续滚动
                    int oldAction = event.getAction();
                    event.setAction(MotionEvent.ACTION_DOWN);
                    dispatchTouchEvent(event);
                    event.setAction(oldAction);
                }
                break;


            case MotionEvent.ACTION_UP:
                //松手后,看位置,如果过半,刷新头全部显示,没过半,刷新头全部隐藏
                if (mLp.topMargin > -mHeaderHeight / 2) {
                    smoothChangeTopMargin(mLp.topMargin, 0);
                } else {
                    smoothChangeTopMargin(mLp.topMargin, -mHeaderHeight);
                }

                break;
        }

        mLastY = y;
        lastActiveId = curActiveId;//别忘了,更新上次的操控手指id

        return true;
    }

    /**
     * 使用属性动画平滑地过度topMargin
     *
     * @param start
     * @param end
     */
    private void smoothChangeTopMargin(int start, int end) {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(start, end);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mLp.topMargin = (int) animation.getAnimatedValue();
                mHeader.setLayoutParams(mLp);

            }
        });
        valueAnimator.setDuration(300);
        valueAnimator.start();

    }
}

MiniMax H3本地部署与ComfyUI集成实战:从环境配置到提示词优化 文本到视频生成是AI内容创作领域的关键技术,它基于扩散模型等深度学习原理,将自然语言描述转化为连贯的动态视觉序列。这项技术的核心价值在于大幅降低了视频制作的门槛,为短视频创作、概念可视化、教育内容生成等场景提供了高效工具。在实际工程实践中,成功部署和运行此类模型,如近期备受关注的MiniMax H3,需要精准处理环境配置、显存优化和提示词工程等环节。其中,解决“CUDA error: no kernel image is available”等版本兼容性问题,以及针对“8G显存”等有限资源进行参数调优,是确 阅读详情

相关推荐

VASPKIT绘制平面平均电荷差分密度

平面平均密度差(planar-averaged electron density difference)是密度差的衍生。密度差是个三维空间函数,经常通过绘制平面图、等值面图方式图形化考察。虽然这两种图很直观,但平面图会受到截面选取的影响,而等值面图会受到等值面数值(isovalue)选取的影响,因此都有一定任意性,也不容易定量讨论。对于电子转移有比较明确方向的情况,可以绘制平面平均密度差曲线,由此可以清楚地考察垂直于选取的方向上每个截面上的密度差积分值,在定量讨论、对比上比较便利。

weixin_43948934的博客 1万+

Android手势操作(双击,长按,滑动,滚动,多点触控)

源码分享:https://github.com/heinika/GestureListener 主要使用到GestureDetector 这个类:在实际使用中一般使用他们的子类GestureDetector.SimpleOnGestureListener() 下面自定义一个View实现手势操作: public class MyButton extends Button { pr

heinika的专栏 7778

UE5导入MetaHuman虚拟头像后,连接live link face,面部表情捕捉出错修正

UE5 利用live link face 驱动meta human面部表情捕捉

m0_53122690的博客 6596

Android多点触控之——MotionEvent(触控事件)

今天晚上刚学习了一个多点触控的小程序,后面想对其做一个定制。在写的时候遇到很多问题,于是乎就查了一下API文档,又到网上查了一下高手的文章,最后自己又实践了一下。终于把多点触控事件监听的大概原理给弄清楚了。下面就写一下我个人对多点触控原理的理解: 一、MotionEvent事件的分类       触控分为两类:单点触控和多点触控。       1、如何获取触控事件信息?         安

David-Kuper的专栏 1万+

Hand-Eye 标定误差分析:从理论到 C++ 实现

本文深入探讨了机器人手眼标定中的核心环节——误差分析。文章从AX=XB方程的理论残差出发,详细解析了旋转与平移误差的数学定义与物理意义,并提供了一个工业级的C++实现代码,用于计算重投影误差。通过误差分析,工程师可以量化标定精度,诊断问题根源,从而确保视觉引导机器人系统在实际应用中的可靠性与精确性。

c7d8e的博客 697

EtherCAT主站SOEM -- 24 -- 基于STM32F767IGT6搭建自己的SOEM-EtherCAT主站

以上就是EtherCAT主站SOEM – 23 – 基于STM32F767IGT6搭建自己的SOEM-EtherCAT主站的内容。有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。创作不容,如果文档对您有帮助,记得给个赞。

常驻客栈的博客--嵌入式EtherCAT 3560

android多指触控失效,安卓--多指触控

1、体验与发现首先看一下代码:@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getActionMasked()) {case MotionEvent.ACTION_DOWN:Log.i(TAG, "viewSizeHandle: down"+event.getActionIndex());break;c...

weixin_34324006的博客 1581

内网渗透(二)之基础知识-工作组介绍

在一个大型单位里,可能有成百上千台计算机互相连接组成局域网,它们都会列在"网络"(网上邻居)内。如果不对这些计算机进行分组,网络的混乱程度是可想而知的 为了解决这一问题,产生了工作组( Work Group)这个概念。将不同的计算机按功能(或部 门)分别列入不同的工作组,例如技术部的计算机都列入"技术部"工作组、行政部的计算机都 列入"行政部"工作组。要想访问某个部门的资源,只要在"网络"里双击该部门的工作组名 就可以看到该部门的所有计算机了。相比不分组的情况,这样的情况有序得多(尤其对大型局域网来说)。

把自己活成一道光,因为你不知道,谁会借着你的光,走出了黑暗。请保持心中的善良,因为你不知道,谁会借着你的善良,走出了绝望。请保持你心中的信仰,因为你不知道,谁会借着你的信仰,走出了迷茫。请相信自己的力量,因为你不知道,谁会因为相信你,开始相信了自己.... 1219

[android大坑]ACTION_POINTER_DOWN事件无法触发

长话短说: 有个需求是做双指缩放和旋转,然后做这个功能需要重写onTouchEvent方法,监听ACTION_POINTER_DOWN事件。 然后偶,这个ACTION_POINTER_DOWN一直没触发。监听不到这个事件做个锤子双指缩放、旋转偶。 然后就各种百度偶,也是百度不到。 最后在一个人的代码里面看到了这么一段代码: switch (action & MotionEven...

欢迎进入JesseAndroid的博客 6981

5G射频设计中N77&N79的PRX为什么需要3个SRS

首先,我们来逐个拆解一下这个神秘的“

weixin_43199439的博客 1325

AIGC算法工程师面试八股文深度解析与进阶指南:揭秘Diffusion Models核心原理与实战技巧

总结来说,Cosine Noise Scheduler 的核心优势在于它能够更巧妙地平衡信号和噪声的比例,在扩散过程的早期阶段更长时间地保留原始图像的细节信息,从而为去噪模型提供一个更友好的学习环境,最终带来更优异的生成质量。🚀

FJN110的博客 346

多点触摸简单手势处理方法

1.单点点击     直接用点击时间+点击时间(按住时间)处理 2.单点滑动(拖动)     分解为x,y方向的移动矢量,处理位移 3.两点平移     计算新旧两对触摸点坐标之间中心点的偏移 4.两点缩放     计算新旧两对触摸点坐标之间的距离差 5.两点旋转     计算修旧两对触摸点之间的向量的到角(矢量的,不是标量夹角) 6.两点以上触摸     结合具体手势,参照

左木右易 956

肖特基二极管选型参数,结构原理,工艺与注意问题总结

肖特基二极管(Schottky Diode)是一种特殊的二极管,也被称为肖特基势垒二极管。它是利用金属与半导体接触形成的金属-半导体结原理制成的。与传统的PN结二极管相比,肖特基二极管具有更低的正向压降、更高的开关速度、更高的反向恢复时间以及更好的温度稳定性等特点。本文对肖特基二极管的工作原理,结构特点,工艺流程,选型参数及设计注意事项进行总结。

fydar的博客 814

11个处理触摸事件和多点触摸的JS库

触摸屏是现在所有智能手机的标配,还包括各种平板设备,而且很多桌面也慢慢在开始支持触摸操作。要开发支持触摸屏设备的Web应用,我们需要借助浏览器的触摸事件来实现。下图是各种触摸事件说明:本文我们介绍11个用来处理触摸事件以及支持多点触摸的JS库:1.QUO JSQuoJS是一个小型、模块化、面向对象的JavaScript库,用于移动Web开发中简化HTML文档遍历、事件处理和Ajax交互等功能。Ev

Webapp html5 1118

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

如何“排外”处理多点触摸事件

Other views in the same window can still receive touch events when this property is NO. If you want this view to handle multi-touch events exclusively, set the values of both this property and the exc

酷酷的哀殿的专栏 1495

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

android 多点触摸交互处理

今天介绍一下多点触摸交互处理,过程中会有几个小demo。首先,我为什么要有学习这块呢?因为他涉及到图片的缩放啊,类似的一些操作,现在的app都必不可少。要想做图片的缩放,首先要知道手指在哪里。     第一,如何获取手指在滑动中的坐标?    这个可以通过view的onTouchListener实现,在过程中实现,一定一定要注意,把onTouch的方法返回true,默认是false的,因为fa

yx1166的博客 482

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

android开发之多点触摸交互处理

懒惰,只是为了更好地懒惰!

ZaneLove's blog 1166

基于Visual C#2010开发Windows7应用 多点触摸图片处理应用程序(2)-使用多点触摸操作处理图片

到目前为止,使用触摸事件处理图片与使用鼠标功能并没有太大区别。下面我们将: •               添加使用多个手指操作图片的能力 •               同时平移、缩放和旋转图片 •               同时操作多张图片 我们已经知道如何将正确的事件分派给相应的 PictureTracker,但我们还不知道如何决定在发生多个事件之后需要采取的操作。这正是

尹成的技术博客 8552

Android多点触摸交互处理

版权声明:本文为博主原创文章,若需转载,请注明出处:http://blog.youkuaiyun.com/suwu150 安卓手机中,多点触摸是是最基本的操作,下面就使用程序进行演示多点触摸操作 一、获取触摸事件中的点击,移动和抬起事件,创建新的安卓项目,如下面代码所示,分别为MainActivity类代码和Layout布局文件,用于实现获取点击事件 1.1、MainActivity类中代码,代码中

sinat_30474567的博客 482

11个处理触摸事件和多点触摸的JS库(转载)

  11个处理触摸事件和多点触摸的JS库(转载) 触摸屏是现在所有智能手机的标配,还包括各种平板设备,而且很多桌面也慢慢在开始支持触摸操作。要开发支持触摸屏设备的Web应用,我们需要借助浏览器的触摸事件来实现。 下图是各种触摸事件说明: 本文我们介绍11个用来处理触摸事件以及支持多点触摸的JS库: 1.QUO JS QuoJS是一个小型、模块化、面向对象的JavaScri...

pucxin 542

基于Visual C#2010开发Windows7应用 多点触摸图片处理应用程序(1)-同时处理多张图片

       windows7的触摸功能开辟了一个电脑的全新世纪。从此,您可以丢掉鼠标和键盘,直接用手在屏幕上玩游戏、用笔来写字编辑文档,聊天。        windows7最重要特性之一就是:支持多点触摸。比尔盖茨说,不久,鼠标键盘会消失。 Windows 7 使用户无需使用中间设备,通过手指触摸方式就能够管理应用程序。与其他指点设备不同,这种新功能支持在不同指点位置上同时发生多个输入事件

尹成的技术博客 1万+

ios触摸超出_iOS开发笔记之多点触控(一)处理触摸的4个方法

多点触控乃苹果公司带给世界的创新之首,作为移动开发者,熟练掌握多点触控开发技能很有必要。处理触摸的四个方法:-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event //首次在屏幕上检测到触摸时调用{NSLog(@"touchesBegan");}-(void)touchesMoved:(NSSet *)touches ...

weixin_39743511的博客 496

基于Visual C 2010开发Windows7应用 多点触摸图片处理应用程序 1 同时处理多张图片

基于Visual C 2010开发Windows7应用 多点触摸图片处理应用程序 1 同时处理多张图片

fdgugfv的博客 304

android怎么监听多点触摸_Android多点触摸交互处理

触摸操作是安卓最基本的交互方法,掌握多点触摸的开发可增强应用交互体验。首先需要了解触摸事件的侦听和传递,同时,本文介绍了单点、多点触摸的使用方法,并在此基础上,使用多点触控完成了一个缩放照片的简单例子。1.触摸事件的侦听初始化页面根布局,通过findViewById查找到privateRelativeLayoutroot;root= (RelativeLayout) findViewById(R....

weixin_39537049的博客 381
上一篇: 触摸事件分发机制(有用的小技巧:事件二次分发)
Android_Study_OK
博客等级 码龄11年 91粉丝 128原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值