add software "mouse cursor" in Android-x86


https://sourceforge.net/p/vilivs5/framework_base/ci/41d38532eb9cc8a3bf6742abb344d86cd40639f1/


This is a rework of mouse cursor for eclair that merges all patches
into one. Also incorporates the button features from 0xdroid:

Menu: Middle button
Back: Right button

I think it's more convenient.

Chih-Wei HuangChih-Wei Huang2010-02-25


changedcore/java/android/view/RawInputEvent.java
changedinclude/ui/EventHub.h
changedlibs/ui/EventHub.cpp
changedservices/java/com/android/server/InputDevice.java
changedservices/java/com/android/server/KeyInputQueue.java
changedservices/java/com/android/server/WindowManagerService.java
--- a/core/java/android/view/RawInputEvent.java
+++ b/core/java/android/view/RawInputEvent.java
@@ -15,6 +15,7 @@
     public static final int CLASS_TRACKBALL = 0x00000008;
     public static final int CLASS_TOUCHSCREEN_MT = 0x00000010;
     public static final int CLASS_DPAD = 0x00000020;
+    public static final int CLASS_MOUSE= 0x00000040;
     
     // More special classes for QueuedEvent below.
     public static final int CLASS_CONFIGURATION_CHANGED = 0x10000000;

--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -57,7 +57,8 @@
         CLASS_TOUCHSCREEN   = 0x00000004,
         CLASS_TRACKBALL     = 0x00000008,
         CLASS_TOUCHSCREEN_MT= 0x00000010,
-        CLASS_DPAD          = 0x00000020
+        CLASS_DPAD          = 0x00000020,
+        CLASS_MOUSE         = 0x00000040
     };
     uint32_t getDeviceClasses(int32_t deviceId) const;

--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -652,7 +652,10 @@
         if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
         {
             if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
-                device->classes |= CLASS_TRACKBALL;
+                if (test_bit(BTN_LEFT, key_bitmask) && test_bit(BTN_RIGHT, key_bitmask))
+                    device->classes |= CLASS_MOUSE;
+                else
+                    device->classes |= CLASS_TRACKBALL;
             }
         }
     }

--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -24,10 +24,13 @@
 
 import java.io.FileInputStream;
 import java.util.StringTokenizer;
+import android.view.RawInputEvent;
 
 public class InputDevice {
     static final boolean DEBUG_POINTERS = false;
     static final boolean DEBUG_HACKS = false;
+    static final boolean DEBUG_MOUSE = false;
+    static final String TAG = "InputDevice";
     
     /** Amount that trackball needs to move in order to generate a key event. */
     static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
@@ -524,13 +527,13 @@
         MotionEvent generateAbsMotion(InputDevice device, long curTime,
                 long curTimeNano, Display display, int orientation,
                 int metaState) {
-            
+            boolean isMouse = (device.classes & RawInputEvent.CLASS_MOUSE) != 0;
             if (mSkipLastPointers) {
                 mSkipLastPointers = false;
                 mLastNumPointers = 0;
             }
             
-            if (mNextNumPointers <= 0 && mLastNumPointers <= 0) {
+            if (!isMouse && (mNextNumPointers <= 0 && mLastNumPointers <= 0)) {
                 return null;
             }
             
@@ -541,24 +544,28 @@
                         + " exceeded maximum of " + MAX_POINTERS);
                 mNextNumPointers = MAX_POINTERS;
             }
-            
-            int upOrDownPointer = updatePointerIdentifiers();
+
+            /*
+             * This is not used for mouse
+             */
+            int upOrDownPointer = isMouse ? 0 : updatePointerIdentifiers();
             
             final float[] reportData = mReportData;
             final int[] rawData;
-            if (KeyInputQueue.BAD_TOUCH_HACK) {
+            if (!isMouse && KeyInputQueue.BAD_TOUCH_HACK) {
                 rawData = generateAveragedData(upOrDownPointer, lastNumPointers,
                         nextNumPointers);
             } else {
-                rawData = mLastData;
-            }
-            
-            final int numPointers = mLastNumPointers;
-            
-            if (DEBUG_POINTERS) Log.v("InputDevice", "Processing "
+                rawData = isMouse ? mNextData : mLastData;
+            }
+            
+            final int numPointers = isMouse ? 1 : mLastNumPointers;
+            
+            if (DEBUG_POINTERS || DEBUG_MOUSE)
+                    Log.v("InputDevice", "Processing "
                     + numPointers + " pointers (going from " + lastNumPointers
-                    + " to " + nextNumPointers + ")");
-            
+                    + " to " + nextNumPointers + ")" + " touch hack "
+                    + KeyInputQueue.BAD_TOUCH_HACK);
             for (int i=0; i<numPointers; i++) {
                 final int pos = i * MotionEvent.NUM_SAMPLE_DATA;
                 reportData[pos + MotionEvent.SAMPLE_X] = rawData[pos + MotionEvent.SAMPLE_X];
@@ -566,29 +573,48 @@
                 reportData[pos + MotionEvent.SAMPLE_PRESSURE] = rawData[pos + MotionEvent.SAMPLE_PRESSURE];
                 reportData[pos + MotionEvent.SAMPLE_SIZE] = rawData[pos + MotionEvent.SAMPLE_SIZE];
             }
-            
+
             int action;
             int edgeFlags = 0;
-            if (nextNumPointers != lastNumPointers) {
-                if (nextNumPointers > lastNumPointers) {
-                    if (lastNumPointers == 0) {
+            if (!isMouse) {
+                 if (nextNumPointers != lastNumPointers) {
+                    if (nextNumPointers > lastNumPointers) {
+                        if (lastNumPointers == 0) {
+                            action = MotionEvent.ACTION_DOWN;
+                            mDownTime = curTime;
+                        } else {
+                            action = MotionEvent.ACTION_POINTER_DOWN
+                                    | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
+                        }
+                    } else {
+                        if (numPointers == 1) {
+                             action = MotionEvent.ACTION_UP;
+                        } else {
+                            action = MotionEvent.ACTION_POINTER_UP
+                                | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
+                        }
+                    }
+                    currentMove = null;
+                } else {
+                    action = MotionEvent.ACTION_MOVE;
+                }
+            } else {
+                if (mNextNumPointers != mLastNumPointers) {
+                    if (mNextNumPointers == 1) {
                         action = MotionEvent.ACTION_DOWN;
                         mDownTime = curTime;
-                    } else {
-                        action = MotionEvent.ACTION_POINTER_DOWN
-                                | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
-                    }
-                } else {
-                    if (numPointers == 1) {
+                    } else if (mNextNumPointers == 2) {
                         action = MotionEvent.ACTION_UP;
                     } else {
-                        action = MotionEvent.ACTION_POINTER_UP
-                                | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
-                    }
-                }
-                currentMove = null;
-            } else {
-                action = MotionEvent.ACTION_MOVE;
+                        action = MotionEvent.ACTION_MOVE;
+                    }
+                    mLastNumPointers = mNextNumPointers;
+                    currentMove = null;
+                } else {
+                    action = MotionEvent.ACTION_MOVE;
+                }
+                if (DEBUG_MOUSE)
+                    Log.i(TAG, "mouse action " + action);
             }
             
             final int dispW = display.getWidth()-1;
@@ -670,7 +696,7 @@
             }
             
             if (currentMove != null) {
-                if (false) Log.i("InputDevice", "Adding batch x="
+                if (DEBUG_MOUSE) Log.i("InputDevice", "Adding batch x="
                         + reportData[MotionEvent.SAMPLE_X]
                         + " y=" + reportData[MotionEvent.SAMPLE_Y]
                         + " to " + currentMove);
@@ -688,7 +714,7 @@
                 currentMove = me;
             }
             
-            if (nextNumPointers < lastNumPointers) {
+            if ((!isMouse) && (nextNumPointers < lastNumPointers)) {
                 removeOldPointer(upOrDownPointer);
             }

--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -47,10 +47,13 @@
 
 public abstract class KeyInputQueue {
     static final String TAG = "KeyInputQueue";
+    static final int UPKEY_KEYWORD = 19;
+    static final int DOWNKEY_KEYWORD = 20;
 
     static final boolean DEBUG = false;
     static final boolean DEBUG_VIRTUAL_KEYS = false;
     static final boolean DEBUG_POINTERS = false;
+    static final boolean DEBUG_MOUSE = false;
     
     /**
      * Turn on some hacks we have to improve the touch interaction with a
@@ -76,6 +79,8 @@
     Display mDisplay = null;
     int mDisplayWidth;
     int mDisplayHeight;
+    int mCx;
+    int mCy;
     
     int mOrientation = Surface.ROTATION_0;
     int[] mKeyRotationMap = null;
@@ -311,6 +316,8 @@
         // buttons based on that display.
         mDisplayWidth = display.getWidth();
         mDisplayHeight = display.getHeight();
+        mCx = mDisplayWidth / 2;
+        mCy = mDisplayHeight / 2;
     }
     
     public void getInputConfiguration(Configuration config) {
@@ -629,11 +636,35 @@
                                 di.mAbs.mDown[0] = ev.value != 0;
                             
                             // Trackball (mouse) protocol: press down or up.
-                            } else if (ev.scancode == RawInputEvent.BTN_MOUSE &&
-                                    (classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
-                                di.mRel.changed = true;
-                                di.mRel.mNextNumPointers = ev.value != 0 ? 1 : 0;
-                                send = true;
+                            } else if (ev.scancode == RawInputEvent.BTN_MOUSE) {
+                                if ((classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
+                                    di.mRel.changed = true;
+                                    di.mRel.mNextNumPointers = ev.value != 0 ? 1 : 0;
+                                    send = true;
+                                } else if ((classes&RawInputEvent.CLASS_MOUSE) != 0) {
+                                    if (DEBUG_MOUSE)
+                                        Log.i(TAG, "Mouse key event found, down:"
+                                            + ev.value + " was :" +
+                                            di.mAbs.mDown[0] + " Send " + send);
+                                    di.mAbs.changed = true;
+                                    di.mAbs.mNextNumPointers = (ev.value != 0) ? 1 : 2;
+                                    send = true;
+                                }
+                            } else if ((ev.scancode == RawInputEvent.BTN_RIGHT ||
+                                    ev.scancode == RawInputEvent.BTN_MIDDLE) &&
+                                    (classes&RawInputEvent.CLASS_MOUSE) != 0) {
+                                boolean down = (ev.value != 0);
+                                if (down)
+                                    di.mKeyDownTime = curTime;
+
+                                addLocked(di, curTime, ev.flags,
+                                    RawInputEvent.CLASS_KEYBOARD,
+                                    newKeyEvent(di, di.mKeyDownTime, curTime, down,
+                                        (ev.scancode == RawInputEvent.BTN_RIGHT)
+                                        ? KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_MENU,
+                                        0, scancode,
+                                        ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0)
+                                        ? KeyEvent.FLAG_WOKE_HERE : 0));
                             }
     
                         // Process position events from multitouch protocol.
@@ -687,15 +718,59 @@
                             }
     
                         // Process movement events from trackball (mouse) protocol.
-                        } else if (ev.type == RawInputEvent.EV_REL &&
-                                (classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
-                            // Add this relative movement into our totals.
-                            if (ev.scancode == RawInputEvent.REL_X) {
-                                di.mRel.changed = true;
-                                di.mRel.mNextData[MotionEvent.SAMPLE_X] += ev.value;
-                            } else if (ev.scancode == RawInputEvent.REL_Y) {
-                                di.mRel.changed = true;
-                                di.mRel.mNextData[MotionEvent.SAMPLE_Y] += ev.value;
+                        } else if (ev.type == RawInputEvent.EV_REL) {
+                            if (DEBUG_MOUSE)
+                                Log.i(TAG, "rel event found, class :" + classes + " mouse value: " + RawInputEvent.CLASS_MOUSE);
+                            if ((classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
+                                // Add this relative movement into our totals.
+                                if (ev.scancode == RawInputEvent.REL_X) {
+                                    di.mRel.changed = true;
+                                    di.mRel.mNextData[MotionEvent.SAMPLE_X] += ev.value;
+                                } else if (ev.scancode == RawInputEvent.REL_Y) {
+                                    di.mRel.changed = true;
+                                    di.mRel.mNextData[MotionEvent.SAMPLE_Y] += ev.value;
+                                }
+                            } else if ((classes&RawInputEvent.CLASS_MOUSE) != 0) {
+                                if (ev.scancode == RawInputEvent.REL_X) {
+                                    di.mAbs.changed = true;
+                                    mCx += (int)ev.value;
+                                    mCx = ((mCx < 0) ? 0 : (mCx >= mDisplayWidth ? mDisplayWidth - 1 : mCx));
+                                    di.mAbs.mNextData[MotionEvent.SAMPLE_X] = mCx;
+                                } else if (ev.scancode == RawInputEvent.REL_Y) {
+                                    di.mAbs.changed = true;
+                                    mCy += (int)ev.value;
+                                    mCy = ((mCy < 0) ? 0 : (mCy >= mDisplayHeight ? mDisplayHeight - 1 : mCy));
+                                    di.mAbs.mNextData[MotionEvent.SAMPLE_Y] = mCy;
+                                } else if (ev.scancode == RawInputEvent.REL_WHEEL &&
+                                               (classes&RawInputEvent.CLASS_MOUSE) != 0) {
+                                    boolean down;
+                                    int keycode;
+                                    if (ev.value != 0) {
+                                        down = true;
+                                        di.mKeyDownTime = curTime;
+                                    } else {
+                                        down = false;
+                                    }
+                                    if (ev.value < 0){
+                                        keycode = rotateKeyCodeLocked(DOWNKEY_KEYWORD);
+                                    } else if(ev.value > 0){
+                                        keycode = rotateKeyCodeLocked(UPKEY_KEYWORD);
+                                    } else {
+                                        keycode = rotateKeyCodeLocked(ev.keycode);
+                                    }
+                                    addLocked(di, curTime, ev.flags,
+                                            RawInputEvent.CLASS_KEYBOARD,
+                                            newKeyEvent(di, di.mKeyDownTime, curTime, down,
+                                                    keycode, 0, scancode,
+                                                    ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0)
+                                                    ? KeyEvent.FLAG_WOKE_HERE : 0));
+                                    addLocked(di, curTime, ev.flags,
+                                            RawInputEvent.CLASS_KEYBOARD,
+                                            newKeyEvent(di, di.mKeyDownTime, curTime, !down,
+                                                    keycode, 0, scancode,
+                                                    ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0)
+                                                    ? KeyEvent.FLAG_WOKE_HERE : 0));
+                                }
                             }
                         }
                         
@@ -778,7 +853,8 @@
                                             me = ms.generateAbsMotion(di, curTime,
                                                     curTimeNano, mDisplay,
                                                     mOrientation, mGlobalMetaState);
-                                            if (DEBUG_POINTERS) Log.v(TAG, "Absolute: x="
+                                            if (DEBUG_POINTERS || DEBUG_MOUSE)
+                                                Log.v(TAG, "Absolute: x="
                                                     + di.mAbs.mNextData[MotionEvent.SAMPLE_X]
                                                     + " y="
                                                     + di.mAbs.mNextData[MotionEvent.SAMPLE_Y]
@@ -787,8 +863,15 @@
                                                 if (WindowManagerPolicy.WATCH_POINTER) {
                                                     Log.i(TAG, "Enqueueing: " + me);
                                                 }
-                                                addLocked(di, curTimeNano, ev.flags,
-                                                        RawInputEvent.CLASS_TOUCHSCREEN, me);
+                                                if ((classes & RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
+                                                    addLocked(di, curTime, ev.flags,
+                                                            RawInputEvent.CLASS_TOUCHSCREEN, me);
+                                                } else if ((classes & RawInputEvent.CLASS_MOUSE) != 0) {
+                                                    addLocked(di, curTime, ev.flags,
+                                                            RawInputEvent.CLASS_MOUSE, me);
+                                                } else {
+                                                    Log.w(TAG, "Unknown classes? " + classes);
+                                                }
                                             }
                                         } while (ms.hasMore());
                                     } else {

--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -58,6 +58,7 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Matrix;
+import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -126,6 +127,9 @@
 import java.util.Iterator;
 import java.util.List;
 
+import android.graphics.Canvas;
+import android.graphics.Path;
+
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
         implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
@@ -357,6 +361,13 @@
     private DimAnimator mDimAnimator = null;
     Surface mBlurSurface;
     boolean mBlurShown;
+
+    Surface mMouseSurface;
+    int mShowMouse = 0;
+    int mMlx;
+    int mMly;
+    int mMlw;
+    int mMlh;
 
     int mTransactionSequence = 0;
 
@@ -5112,7 +5123,7 @@
         // dispatch the event.
         try {
             if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
-                Log.v(TAG, "Delivering pointer " + qev + " to " + target);
+                Log.v(TAG, "Delivering pointer " + qev + " Ev " + ev + " to " + target);
             }
             
             if (MEASURE_LATENCY) {
@@ -6021,7 +6032,7 @@
                 if (qev != null) {
                     res = (MotionEvent)qev.event;
                     if (DEBUG_INPUT) Log.v(TAG,
-                            "Returning pending motion: " + res);
+                            "Returning pending motion: " + res + "q: " + qev);
                     mQueue.recycleEvent(qev);
                     if (win != null && returnWhat == RETURN_PENDING_POINTER) {
                         res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
@@ -6254,7 +6265,8 @@
                     if (screenIsOff) {
                         if (!mPolicy.isWakeRelMovementTq(event.deviceId,
                                 device.classes, event)) {
-                            //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
+                            if (DEBUG_INPUT)
+                                Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
                             return false;
                         }
                         event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
@@ -6400,7 +6412,8 @@
                         if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
                             eventType = eventType((MotionEvent)ev.event);
                         } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
-                                    ev.classType == RawInputEvent.CLASS_TRACKBALL) {
+                                   ev.classType == RawInputEvent.CLASS_TRACKBALL ||
+                                   ev.classType == RawInputEvent.CLASS_MOUSE) {
                             eventType = LocalPowerManager.BUTTON_EVENT;
                         } else {
                             eventType = LocalPowerManager.OTHER_EVENT;
@@ -6459,6 +6472,38 @@
                                 break;
                             case RawInputEvent.CLASS_TOUCHSCREEN:
                                 //Log.i(TAG, "Read next event " + ev);
+                                dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
+                                break;
+                            case RawInputEvent.CLASS_MOUSE:
+                                MotionEvent mmev = (MotionEvent)ev.event;
+                                int mcx = (int)mmev.getX();
+                                int mcy = (int)mmev.getY();
+
+                                if (mMouseSurface != null && (mMlx != mcx || mMly != mcy)) {
+                                    Surface.openTransaction();
+                                    if (DEBUG_INPUT)
+                                        Log.i(TAG, "Open transaction for the mouse surface");
+                                    WindowState top =
+                                        (WindowState)mWindows.get(mWindows.size() - 1);
+                                    try {
+                                        if (DEBUG_INPUT)
+                                            Log.i(TAG, "Move surf, x: " +
+                                                  Integer.toString(mcx) + " y:"
+                                                  + Integer.toString(mcy));
+
+                                        mMouseSurface.setPosition(mcx, mcy);
+                                        mMouseSurface.setLayer(top.mAnimLayer + 1);
+                                        if (mShowMouse != 1) {
+                                            mMouseSurface.show();
+                                            mShowMouse = 1;
+                                        }
+                                        mMlx = mcx;
+                                        mMly = mcy;
+                                    } catch ( RuntimeException e) {
+                                        Log.e(TAG, "Failure showing mouse surface",e);
+                                    }
+                                    Surface.closeTransaction();
+                                }
                                 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
                                 break;
                             case RawInputEvent.CLASS_TRACKBALL:
@@ -9375,6 +9420,61 @@
 
         if (mFxSession == null) {
             mFxSession = new SurfaceSession();
+        }
+
+        if (mMouseSurface == null) {
+            int mMx, mMy, mMw, mMh;
+            Canvas mCanvas;
+            Path mPath = new Path();
+
+            if (DEBUG_INPUT)
+                Log.i(TAG, "Create Mouse Surface");
+
+            mMw = 12;
+            mMh = 20;
+            mMx = (mDisplay.getWidth() - mMw) / 2;
+            mMy = (mDisplay.getHeight() - mMh) / 2;
+
+            try {
+
+                /*
+                 *First Mouse event, create Surface
+                 */
+
+                mMouseSurface =
+                    new Surface(mFxSession,
+                                0, -1, mMw, mMh,
+                                PixelFormat.TRANSPARENT,
+                                Surface.FX_SURFACE_NORMAL);
+                mCanvas = mMouseSurface.lockCanvas(null);
+                Paint tPaint = new Paint();
+                tPaint.setStyle(Paint.Style.STROKE);
+                tPaint.setStrokeWidth(2);
+                tPaint.setColor(0xffffffff);
+                mPath.moveTo(0.0f, 0.0f);
+                mPath.lineTo(12.0f, 12.0f);
+                mPath.lineTo(7.0f, 12.0f);
+                mPath.lineTo(11.0f, 20.0f);
+                mPath.lineTo(8.0f, 21.0f);
+                mPath.lineTo(4.0f, 13.0f);
+                mPath.lineTo(0.0f, 17.0f);
+                mPath.close();
+                mCanvas.clipPath(mPath);
+                mCanvas.drawColor(0xff000000);
+                mCanvas.drawPath(mPath, tPaint);
+
+                mMouseSurface.unlockCanvasAndPost(mCanvas);
+                mMouseSurface.openTransaction();
+                mMouseSurface.setSize(mMw, mMh);
+                mMouseSurface.closeTransaction();
+
+            } catch (Exception e) {
+                Log.e(TAG, "Exception creating mouse surface",e);
+            }
+            mMlx = mMx;
+            mMly = mMy;
+            mMlw = mMw;
+            mMlh = mMh;
         }
 
         if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值