Android 触摸屏校准

话接上回,我们发现了手工利用 tslib 校验触摸屏的缺点。那么这一回 我们就来一次稍微高级一点的校验吧。

我们其实只需要相对的 x,y 以及lcd的 x,y 就可以把校验系数算出来。这里要说的是lcd的x,y是绝对的准确的 比如我们要在(50,50)画一个十字 那么这个50,50就是我们认为的绝对坐标。我们要的只是从android通过getX()和getY()拿到我们需要的相对坐标。

其实一切我们打算做的事情可以都在 InputDevice 里面做完

下面我把完整之后整个的 InputDevice 贴出来:

*
 * Copyright ( C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2. 0 ( the "License" ) ;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http: //www.apache.org/licenses/LICENSE-2.0

*
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * /

package com. android. server ;

import android. util . Log ;
import android. view . Display;
import android. view . MotionEvent;
import android. view . Surface;
import android. view . WindowManagerPolicy;
import java . io . FileInputStream ;
import java . util . StringTokenizer ;
import java . io . File ;
import java . io . FileNotFoundException ;
import java . io . FileOutputStream ;
import java . io . IOException ;
public class InputDevice {
    /** Amount that trackball needs to move in order to generate a key event. */
    static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
   
    //once edit

static final String CALIBRATION_FILE = "/data/etc/pointercal" ;
    //edit ends

final int id ;
    final int classes;
    final String name ;
    final AbsoluteInfo absX;
    final AbsoluteInfo absY;
    final AbsoluteInfo absPressure;
    final AbsoluteInfo absSize;
       //once edit

static TransformInfo tInfo;
    //edit ends

long mDownTime = 0;
    int mMetaKeysState = 0;
    static File desFile;
    final MotionState mAbs = new MotionState( 0, 0) ;
    final MotionState mRel = new MotionState( TRACKBALL_MOVEMENT_THRESHOLD,
            TRACKBALL_MOVEMENT_THRESHOLD) ;
   
    static class MotionState {
        int xPrecision;
        int yPrecision;
        float xMoveScale;
        float yMoveScale;
        MotionEvent currentMove = null ;
        boolean changed = false;
        boolean down = false;
        boolean lastDown = false;
        long downTime = 0;
        int x = 0;
        int y = 0;
        int pressure = 1;
        int size = 0;
       
        MotionState( int mx, int my) {
            xPrecision = mx;
            yPrecision = my;
            xMoveScale = mx ! = 0 ? ( 1. 0f/ mx) : 1. 0f;
            yMoveScale = my ! = 0 ? ( 1. 0f/ my) : 1. 0f;
        }
       
        MotionEvent generateMotion( InputDevice device, long curTime,
                boolean isAbs, Display display, int orientation,
                int metaState) {
            if ( ! changed) {
                return null ;
            }
           //once edit

String prop = System . getProperty ( "ts.config.calibrate" , "noset" ) ;
        if ( prop. equalsIgnoreCase ( "start" ) ) {
            Log . i( "XXW prop" , prop) ;
            Log . i( "XXW" , "prop.equalsIgnoreCase start" ) ;
            device. tInfo = null ;
        } else if ( prop. equalsIgnoreCase ( "done" ) ) {
            Log . i( "XXW prop" , prop) ;
            Log . i( "XXW" , "prop.equalsIgnoreCase done" ) ;
            readCalibrate( ) ;
            System . setProperty ( "ts.config.calibrate" , "end" ) ;
        } else {
            Log . i( "XXW prop" , prop) ;
            Log . i( "XXW" , "prop.equalsIgnoreCase else" ) ;
        }
        //edit ends

float scaledX = x;
            float scaledY = y;
            float temp;
            float scaledPressure = 1. 0f;
            float scaledSize = 0;
            int edgeFlags = 0;
            if ( isAbs) {
                int w = display. getWidth ( ) - 1;
                int h = display. getHeight ( ) - 1;
                if ( orientation = = Surface. ROTATION_90
                        | | orientation = = Surface. ROTATION_270) {
                    int tmp = w;
                    w = h;
                    h = tmp;
                }
                if ( device. absX ! = null ) {
                      //once edit

if ( device. tInfo ! = null ) {
                        scaledX = ( device. tInfo. x1 * x + device. tInfo. y1 * y + device. tInfo. z1) / device. tInfo. s;
                     Log . i( "XXW" , "x: " + x) ;
                     Log . i( "XXW" , "trans x: " + scaledX) ;
                    }
                    else
                    //edit ends

scaledX = ( ( scaledX- device. absX. minValue)
                                / device. absX. range) * w;
                }
                if ( device. absY ! = null ) {
                    //once edit

if ( device. tInfo ! = null ) {
                        scaledY = ( device. tInfo. x2 * x + device. tInfo. y2 * y + device. tInfo. z2) / device. tInfo. s;
                    Log . i( "XXW" , "y: " + y) ;

Log . i( "XXW" , "trans y: " + scaledY) ;
                    }
                    else
                    //edit ends

scaledY = ( ( scaledY- device. absY. minValue)
                                / device. absY. range) * h;
                }
                if ( device. absPressure ! = null ) {
                    scaledPressure =
                        ( ( pressure- device. absPressure. minValue)
                                / ( float ) device. absPressure. range) ;
                }
                if ( device. absSize ! = null ) {
                    scaledSize =
                        ( ( size - device. absSize. minValue)
                                / ( float ) device. absSize. range) ;
                }
                switch ( orientation) {
                    case Surface. ROTATION_90:
                        temp = scaledX;
                        scaledX = scaledY;
                        scaledY = w- temp;
                        break ;
                    case Surface. ROTATION_180:
                        scaledX = w- scaledX;
                        scaledY = h- scaledY;
                        break ;
                    case Surface. ROTATION_270:
                        temp = scaledX;
                        scaledX = h- scaledY;
                        scaledY = temp;
                        break ;
                }

if ( scaledX = = 0) {
                    edgeFlags + = MotionEvent. EDGE_LEFT;
                } else if ( scaledX = = display. getWidth ( ) - 1. 0f) {
                    edgeFlags + = MotionEvent. EDGE_RIGHT;
                }
               
                if ( scaledY = = 0) {
                    edgeFlags + = MotionEvent. EDGE_TOP;
                } else if ( scaledY = = display. getHeight ( ) - 1. 0f) {
                    edgeFlags + = MotionEvent. EDGE_BOTTOM;
                }
               
            } else {
                scaledX * = xMoveScale;
                scaledY * = yMoveScale;
                switch ( orientation) {
                    case Surface. ROTATION_90:
                        temp = scaledX;
                        scaledX = scaledY;
                        scaledY = - temp;
                        break ;
                    case Surface. ROTATION_180:
                        scaledX = - scaledX;
                        scaledY = - scaledY;
                        break ;
                    case Surface. ROTATION_270:
                        temp = scaledX;
                        scaledX = - scaledY;
                        scaledY = temp;
                        break ;
                }
            }
           
            changed = false;
            if ( down ! = lastDown) {
                int action ;
                lastDown = down;
                if ( down) {
                    action = MotionEvent. ACTION_DOWN;
                    downTime = curTime;
                } else {
                    action = MotionEvent. ACTION_UP;
                }
                currentMove = null ;
                if ( ! isAbs) {
                    x = y = 0;
                }
                return MotionEvent. obtain( downTime, curTime, action ,
                        scaledX, scaledY, scaledPressure, scaledSize, metaState,
                        xPrecision, yPrecision, device. id , edgeFlags) ;
            } else {
                if ( currentMove ! = null ) {
                    if ( false) Log . i( "InputDevice" , "Adding batch x=" + scaledX
                            + " y=" + scaledY + " to " + currentMove) ;
                    currentMove. addBatch ( curTime, scaledX, scaledY,
                            scaledPressure, scaledSize, metaState) ;
                    if ( WindowManagerPolicy. WATCH_POINTER) {
                        Log . i( "KeyInputQueue" , "Updating: " + currentMove) ;
                    }
                    return null ;
                }
                MotionEvent me = MotionEvent. obtain( downTime, curTime,
                        MotionEvent. ACTION_MOVE, scaledX, scaledY,
                        scaledPressure, scaledSize, metaState,
                        xPrecision, yPrecision, device. id , edgeFlags) ;
                currentMove = me;
                return me;
            }
        }
    }
   
    static class AbsoluteInfo {
        int minValue;
        int maxValue;
        int range;
        int flat;
        int fuzz;
    } ;

//once edit

static class TransformInfo {
       float x1;
       float y1;
       float z1;
       float x2;
       float y2;
       float z2;
       float s;
    } ;
    //edit ends

InputDevice( int _id, int _classes, String _name,
            AbsoluteInfo _absX, AbsoluteInfo _absY,
            AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
        id = _id;
        classes = _classes;
        name = _name;
        absX = _absX;
        absY = _absY;
        absPressure = _absPressure;
        absSize = _absSize;
       
        //once edit

desFile = new File ( CALIBRATION_FILE) ;
        readCalibrate( ) ;
        //edit ends

}

static void readCalibrate( ) {
        //xxw added

Log . i( "XXW" , "readCalibrate!" ) ;
        TransformInfo t = null ;
        try {
            FileInputStream is = new FileInputStream ( CALIBRATION_FILE) ;
            byte [ ] mBuffer = new byte [ 64] ;
            int len = is. read ( mBuffer) ;
            is. close ( ) ;
           
            if ( len > 0) {
                int i;
                for ( i = 0 ; i < len ; i+ + ) {
                    if ( mBuffer[ i] = = '/n' | | mBuffer[ i] = = 0) {
                        break ;
                    }
                }
                len = i;
            }
                               
            StringTokenizer st = new StringTokenizer ( new String ( mBuffer, 0, 0, len) ) ;
            t = new TransformInfo ( ) ;
            t. x1 = Integer . parseInt ( st. nextToken ( ) ) ;
            t. y1 = Integer . parseInt ( st. nextToken ( ) ) ;
            t. z1 = Integer . parseInt ( st. nextToken ( ) ) ;
            t. x2 = Integer . parseInt ( st. nextToken ( ) ) ;
            t. y2 = Integer . parseInt ( st. nextToken ( ) ) ;
            t. z2 = Integer . parseInt ( st. nextToken ( ) ) ;
            t. s = Integer . parseInt ( st. nextToken ( ) ) ;
        } catch ( java . io . FileNotFoundException e) {
            Log . i( "XXW" , "FileNotFound!" ) ;
        } catch ( java . io . IOException e) {
            Log . i( "XXW" , "IOException" ) ;
        }
        tInfo = t;
        Log . i( "XXW" , "readCalibrate done!" ) ;
    }
} ;

与上一次的那个 InputDevice 相比 我将读取校准文件的代码单独的变成一个函数,之所以这么做 是因为我们打算不重启就可以直接让 android 校准完成。 这 里其实也没什么东西 只是读取校验文件 如果读取成功了就用校验公式计算出校准后的坐标。 为了避免重启 所以用了一个系统属性ts.config.calibrate来决定重新读取一次文件。当然 当ts.config.calibrate值表明正在校验的话 就直接传上来点击的原始坐标而不经过换算。校验完成之后读取一次校验文件 然后将系统属性变成其他值不再读取文件。

下面我们就要写一个 apk 来实现校准了。

这里 我尝试了 2 种方法 一种是纯 java 的 apk 一种是 jni 的 apk 。其实对于校准来说 上层已经能拿到 x,y 那么我们取 5 个点就已经可以算出来那 7 个校准值 然后利用 java 存文件了。整个 apk 的java代码

package com. android. calibrate;

import java . io . File ;
import java . io . FileNotFoundException ;
import java . io . FileOutputStream ;
import java . io . IOException ;
import android. util . Log ;

public class Calibrate {
    private calibration cal;

public Calibrate( ) {
        cal = new calibration( ) ;
    }

class calibration {
        int x[ ] = new int [ 5] ;

int xfb[ ] = new int [ 5] ;

int y[ ] = new int [ 5] ;

int yfb[ ] = new int [ 5] ;

int a[ ] = new int [ 7] ;
    } ;

boolean perform_calibration( ) {
        Log . i( "XXW" , "perform_calibration" ) ;
        int j;
        float n, x, y, x2, y2, xy, z, zx, zy;
        float det, a, b, c, e, f, i;
        float scaling = ( float ) 65536. 0;

// Get sums for matrix

n = x = y = x2 = y2 = xy = 0;
        for ( j = 0; j < 5; j+ + ) {
            n + = 1. 0;
            x + = ( float ) cal. x[ j] ;
            y + = ( float ) cal. y[ j] ;
            x2 + = ( float ) ( cal. x[ j] * cal. x[ j] ) ;
            y2 + = ( float ) ( cal. y[ j] * cal. y[ j] ) ;
            xy + = ( float ) ( cal. x[ j] * cal. y[ j] ) ;
        }

// Get determinant of matrix -- check if determinant is too small

det = n * ( x2 * y2 - xy * xy) + x * ( xy * y - x * y2) + y * ( x * xy - y * x2) ;
        if ( det < 0. 1 & & det > - 0. 1) {
            Log . i( "ts_calibrate: determinant is too small -- %f/n" , "" + det) ;
            return false;
        }

// Get elements of inverse matrix

a = ( x2 * y2 - xy * xy) / det;
        b = ( xy * y - x * y2) / det;
        c = ( x * xy - y * x2) / det;
        e = ( n * y2 - y * y) / det;
        f = ( x * y - n * xy) / det;
        i = ( n * x2 - x * x) / det;

// Get sums for x calibration

z = zx = zy = 0;
        for ( j = 0; j < 5; j+ + ) {
            z + = ( float ) cal. xfb[ j] ;
            zx + = ( float ) ( cal. xfb[ j] * cal. x[ j] ) ;
            zy + = ( float ) ( cal. xfb[ j] * cal. y[ j] ) ;
        }

// Now multiply out to get the calibration for framebuffer x coord

cal. a[ 0] = ( int ) ( ( a * z + b * zx + c * zy) * ( scaling) ) ;
        cal. a[ 1] = ( int ) ( ( b * z + e * zx + f * zy) * ( scaling) ) ;
        cal. a[ 2] = ( int ) ( ( c * z + f * zx + i * zy) * ( scaling) ) ;

System . out. printf ( "%f %f %f/n" , ( a * z + b * zx + c * zy) , ( b * z + e * zx + f * zy) , ( c
                * z + f * zx + i * zy) ) ;

// Get sums for y calibration

z = zx = zy = 0;
        for ( j = 0; j < 5; j+ + ) {
            z + = ( float ) cal. yfb[ j] ;
            zx + = ( float ) ( cal. yfb[ j] * cal. x[ j] ) ;
            zy + = ( float ) ( cal. yfb[ j] * cal. y[ j] ) ;
        }

// Now multiply out to get the calibration for framebuffer y coord

cal. a[ 3] = ( int ) ( ( a * z + b * zx + c * zy) * ( scaling) ) ;
        cal. a[ 4] = ( int ) ( ( b * z + e * zx + f * zy) * ( scaling) ) ;
        cal. a[ 5] = ( int ) ( ( c * z + f * zx + i * zy) * ( scaling) ) ;

System . out. printf ( "%f %f %f/n" , ( a * z + b * zx + c * zy) , ( b * z + e * zx + f * zy) , ( c
                * z + f * zx + i * zy) ) ;

// If we got here, we're OK, so assign scaling to a[6] and return

cal. a[ 6] = ( int ) scaling;
        return true;
        /*
         * // This code was here originally to just insert default values
         * for(j=0;j<7;j++) { c->a[j]=0; } c->a[1] = c->a[5] = c->a[6] = 1;
         * return 1;
         */

}

void get_sample( int index, int x1, int y1, int x, int y) {
        Log . i( "XXW" , "get_sample" ) ;
        cal. x[ index] = x1;
        cal. y[ index] = y1;

cal. xfb[ index] = x;
        cal. yfb[ index] = y;
    }

int calibrate_main( ) {
        int result = 0;
        Log . i( "XXW" , "calibrate_main" ) ;
        if ( perform_calibration( ) ) {
            String strPara = String . format ( "%d %d %d %d %d %d %d" , cal. a[ 1] , cal. a[ 2] , cal. a[ 0] ,
                    cal. a[ 4] , cal. a[ 5] , cal. a[ 3] , cal. a[ 6] ) ;

boolean success = new File ( "/data/etc" ) . mkdir ( ) ;
            if ( ! success) {
                Log . i( this . toString ( ) , "no success" ) ;
            }

File desFile = new File ( "/data/etc/pointercal" ) ;
            if ( ! desFile. exists ( ) )
                try {
                    desFile. createNewFile ( ) ;
                } catch ( IOException e1) {
                    e1. printStackTrace ( ) ;
                }
            FileOutputStream fos;

try {
                fos = new FileOutputStream ( desFile) ;
                byte [ ] buf = strPara. getBytes ( ) ;
                int bytesRead = buf. length ;
                try {
                    fos. write ( buf, 0, bytesRead) ;
                    fos. flush ( ) ;
                    fos. close ( ) ;
                } catch ( IOException e) {
                    e. printStackTrace ( ) ;
                }
            } catch ( FileNotFoundException e) {
                e. printStackTrace ( ) ;
            }

result = 0;

} else {
            result = - 1;
        }
        return result ;
    }
}

其实这个就是 tslib 里那个 ts_calibrate.cpp 的姐妹篇。重要的函数就一个 perform_calibration() 。这里要注意的是 你必须首先利用 get_sample 读取 5 个点的值来初始化 cal 然后再调用 calibrate_main 来计算校验系数。而且那 5 个点的顺序为 左上 右上 右下 左下 中间。这 4 个点基本上应该在屏幕的边缘附近 否则计算出来的校验值可能不准。 利用上面的那个类 写一个 apk 出来跑跑看 流程应该就可以了。

package com. android. calibrate;

import com. android. calibrate. R;

import java . util . ArrayList ;
import java . util . List ;

import android. app. Activity ;
import android. os. Bundle;
import android. util . Log ;
import android. view . MotionEvent;
import android. view . View ;
import android. view . Window ;
import android. view . WindowManager;
import android. view . View . OnTouchListener;
import android. widget. ImageView ;
import android. widget. Toast;
import android. os. SystemProperties;
public class AndroidCalibrate extends Activity {
    private Calibrate cal;

private int time ;

private List < ImageView > list = new ArrayList < ImageView > ( ) ;

int xList[ ] = {
            50, 270, 270, 50, 160
    } ;

int yList[ ] = {
            50, 350, 350, 50, 200
    } ;

static void setNotTitle( Activity act) {
        act. requestWindowFeature( Window . FEATURE_NO_TITLE) ;
    }

static void setFullScreen( Activity act) {
        setNotTitle( act) ;
        act. getWindow ( ) . setFlags( WindowManager. LayoutParams. FLAG_FULLSCREEN,
                WindowManager. LayoutParams. FLAG_FULLSCREEN) ;
    }

public void onCreate( Bundle savedInstanceState) {
        super . onCreate( savedInstanceState) ;
        setFullScreen( this ) ;
        this . setContentView( R. layout . main) ;

//System.setProperty("ts.config.calibrate", "start");

//String prop = System.getProperty("ts.config.calibrate", null);

SystemProperty. set ( "ts.config.calibrate" , "start" ) ;
        ImageView image0 = ( ImageView ) findViewById( R. id . crossview_topleft) ;
        ImageView image1 = ( ImageView ) findViewById( R. id . crossview_topright) ;
        ImageView image2 = ( ImageView ) findViewById( R. id . crossview_bottomright) ;
        ImageView image3 = ( ImageView ) findViewById( R. id . crossview_bottomleft) ;
        ImageView image4 = ( ImageView ) findViewById( R. id . crossview_center) ;

image1. setVisibility( View . INVISIBLE) ;
        image2. setVisibility( View . INVISIBLE) ;
        image3. setVisibility( View . INVISIBLE) ;
        image4. setVisibility( View . INVISIBLE) ;

list . clear ( ) ;
        list . add ( image0) ;
        list . add ( image1) ;
        list . add ( image2) ;
        list . add ( image3) ;
        list . add ( image4) ;

for ( ImageView image : list ) {
            image . setOnTouchListener( this . onTouchListener) ;
        }
        cal = new Calibrate( ) ;
        time = 0;
    }

OnTouchListener onTouchListener = new OnTouchListener( ) {
        public boolean onTouch( View v, MotionEvent event ) {
            Log . i( "Property" , SystemProperty. get ( "ts.config.calibrate" , "noset" ) ) ;
            if ( event . getAction ( ) = = MotionEvent. ACTION_DOWN) {
                Log . i( "XXW" , "onTouchListener" ) ;
                v. setVisibility( View . INVISIBLE) ;
                time = list . indexOf ( ( ImageView ) v) ;

if ( time < 5) {
                    if ( time + 1 < 5)
                        list . get ( time + 1) . setVisibility( View . VISIBLE) ;
                    Log . i( "XXW time onTouchListener" , " " + time ) ;
                    cal. get_sample( time , ( int ) event . getX ( ) , ( int ) event . getY ( ) , xList[ time ] ,
                            yList[ time ] ) ;
                    if ( time = = 4) {
                        Log . i( "XXW" , "calibrate_main" ) ;
                        cal. calibrate_main( ) ;
                        Toast. makeText( getBaseContext( ) , "Calibrate Done!" , Toast. LENGTH_SHORT)
                                . show ( ) ;
                        //System.setProperty("ts.config.calibrate", "done");

SystemProperty. set ( "ts.config.calibrate" , "done" ) ;
                        AndroidCalibrate. this . finish ( ) ;
                    }
                }
            }
            return false;
        }
    } ;
}

[转]Android 触摸屏校准相关推荐

  1. Android电阻触摸屏校准

    首先电阻屏为什么需要校准,这是电气方面的知识,我也不懂,这里就不说了,这里主要讲讲自己在项目中是怎么通过应用程序来实现校准的,好记性不如烂笔头这里有一篇讲解触摸屏校准原理和优化的文章,道客巴巴上的,先 ...

  2. linux内核关闭触摸屏校准,触摸屏校正原理

    1,触摸屏校准通用方法 主要采用以下公式,实现触摸屏校正,其中XL, YL是显示屏坐标,XT, YT是触摸屏坐标, XL = XT*A+YT*B+C; YL = XT*D+YT*E+F;    公式( ...

  3. android 触摸屏驱动分析,Android 触摸屏驱动代码分析(ADC 类型触摸屏 CPU:s3c

    Android 2.1 farsight version for s5pc100 File Name: s3c-ts.c 1           简介 1.1          本例基于s5pc100 ...

  4. 简述Android触摸屏手势识别

    很多时候,利用触摸屏的Fling.Scroll等Gesture(手势)操作来操作会使得应用程序的用户体验大大提升,比如用Scroll手势在 浏览器中滚屏,用Fling在阅读器中翻页等.在Android ...

  5. linux蜂鸣器控制实验,【Linux公开课】蜂鸣器使用、LCD背光控制、触摸屏校准、GPIO操作...

    摘要为方便使用蜂鸣器,系统为蜂鸣器提供类似LED的操作接口,对应的操作文件是/sys/class/leds/beep/brightness.写入1使蜂鸣器鸣叫,写入0停止鸣叫- 8.12 蜂鸣器使用 ...

  6. 更改触摸屏校准程序界面提示文字

    BSP中提供的触摸屏校准程序在个别设备上用起来可能不太适合,比如说我们的设备屏幕宽度只有 240pixels,会有部分字符超出屏幕外侧,原以为这是BSP的提供的程序,无源码没办法修改,这两天才知道原来 ...

  7. Android触摸屏驱动屏幕翻转

    项目中移植了Android触摸屏驱动,后来需要把屏幕翻转180度,此时触摸的坐标是没有适配的,修改以下代码即可: frameworks/native/services/inputflinger/Inp ...

  8. android 记录触屏坐标,android触摸屏坐标手工校准/调整成功

    1.简述 android 的坐标转换处理: This implementation is a linear transformation using 7 parameters (a, b, c, d, ...

  9. android触摸屏坐标,android触摸屏坐标手工校准/调整成功

    1.简述 android 的坐标转换处理: This implementation is a linear transformation using 7 parameters (a, b, c, d, ...

最新文章

  1. updateStateByKey--word count
  2. 【linux开发】IO端口和IO内存的区别及分别使用的函数接口
  3. [html] 渐进式渲染是什么?
  4. Leetcode每日一题:204.count-primes(计数质数)
  5. excel 汇总 mysql_利用mysql收集excel录入汇总
  6. Node.js 8有哪些重要功能和修复? 1
  7. Java使用for循环打印菱形
  8. 生物统计学(biostatistics)学习笔记(三)
  9. Power按键流程分析
  10. 零基础入门大数据工程师从底层到应用必备技术汇总
  11. 关联规则Apriori(python实现):Bakery Bussiness Model
  12. 科比投篮预测——可视化与探索性数据分析(二)
  13. 宝塔面板+NextCloud文档云 搭建流程
  14. 大学生申请专利需要多少钱
  15. 谢孟媛老师英语拼读03(附我备注)
  16. ica人脸识别 matlab,ICA算法和人脸识别程序
  17. 跨链技术的分析和思考
  18. (转)理解CPU steal time
  19. 摩斯电码-打码机练习-微信小程序项目开发入门
  20. PaddlePaddle2.0搭建VGG-16模型实现蝴蝶分类

热门文章

  1. 趁热来一波,WWDC 2016 iMessage App开发
  2. Javaweb:Servlet过滤器以及常见应用展示
  3. 一天300个快递,康小康团队都撸些什么商品回来?
  4. 美好停驻,荟语酒店温柔亮相”于姑苏深处,遇锦绣江南”品牌沙龙会
  5. java水仙花数问题详细思路分析以及求解
  6. linux中vi大括号enter缩进,在vi中快速缩进多行
  7. Java进制转换、原码反码补码
  8. 用java写出5的阶乘_java输入一个数n,计算n的阶乘(5的阶乘=1*2*3*4*5)
  9. 零基础咖啡爱好者如何学习咖啡?
  10. kubernetes安全:RBAC,Security Context,PSP,准入控制器