跳转至

主体检测接入文档

文档状态

文件标识: Struct-Detect-V5.1
系统版本: SDK
完成日期: 2022年12月24日

文档修订记录

文档版本号 修订日期 修订原因
V1.0 2022年12月24日 创建文档
V1.1 2023年1月9日 新增接口

概述

用于检测图片中的书本框架,也可矫正倾斜文本。

集成步骤

1. 添加依赖库

//必须依赖库
implementation 'com.google.code.gson:gson:2.6.2'
implementation 'com.squareup.okhttp3:okhttp:3.9.0'
implementation "org.java-websocket:Java-WebSocket:1.4.0"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.aliyun.dpa:oss-android-sdk:2.9.11'//SDKV2.4.1.25 以后需加入

2. AndroidManifest配置

添加权限

    <!--网络-->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />   
    <!--文件读写-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />  
    <!--deviceID-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />  

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <!-- 读取手机状态,获取IMEI -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

    <!-- android 10 在application节点添加以下适配高版本 -->
     android:usesCleartextTraffic="true"
     android:requestLegacyExternalStorage="true"

3. 代码混淆

代码混淆文件proguard-project.txt,添加如下内容


    -keep class com.turing.**{ *;}
    -dontwarn com.turing.**

    -keep class com.tuling.**{ *;}
    -dontwarn com.tuling.**

    -keep class org.java_websocket.**{*;}
    -dontwarn org.java_websocket.**
    -keep class org.slf4j.**{*;}
    -dontwarn org.slf4j.**

    -keep class org.eclipse.** { *; }
    -dontwarn org.eclipse.**

4. SDK 初始化

使用主体检测功能前调用,请先调用SDK初始化代码。SDK初始化详情见《Android SDK接入指南说明文档》

TuringInitializer.getInstance().initV3XXX()

5. 开启功能集成

使用说明见下面【功能集成】描述。

实例化

val turingStruct = TuringStruct.getInstance(this)

功能集成

分为两种方式:异步检测和同步检测。同步方法适合做单次主体检测;异步方法适合:结合相机做实时检测,预览界面绘制主体框。

1. 异步检测

包含主体检测、运动检测。

方法

/**
 * 初始化主体检测,包括运动检测
 */
void initMotionStruct(StructParam param, TuringListenerPro<MAResult> listener);

/**
 * 主体检测,异步方法,包括运动检测,配合initMotionStruct使用,结果会在initMotionStruct接口中回调。
 *
 * 客户端处理图片,请确保传入的图片是正向+非镜像图片。
 */
void MStructDetect(Bitmap srcBmp, boolean ifPad);

/**
 * 主体检测,异步方法,包括运动检测,配合initMotionStruct使用,结果会在initMotionStruct接口中回调。
 * 
 * SDK 结合 StructParam 中的图片参数,将图片处理为正向+非镜像图片。
 * 
 * @param data 图片数据,格式在initMotionStruct中配置。
 */
void MStructDetect(byte[] data);

输入说明

  • StructParam 说明
参数名称 类型 是否必须 描述
previewWidth int Y 图片宽
previewHeight intint Y 图片高
isMirror boolean Y 图片是否镜像
rotation int Y 图片角度。支持90°、180°、270°。
imageFormat int Y 图片格式 仅支持android.graphics.ImageFormat.NV21、 android.graphics.ImageFormat.YUV_420_888
isPad boolean Y true-平板;false-台灯
motionSensitivity int Y 灵敏度

图片参数(宽、高、镜像、角度、格式):调用 MStructDetect(byte[] data) 生效;方法参数为 Bitmap 时,需要客户处理好图片。

  • TuringListenerPro 说明
public interface TuringListenerPro<T> {
    /**
     * 错误回调
     *
     * @param errorCode
     * @param errMsg
     */
    void onError(int errorCode, String errMsg);

    /**
     * 事件回调
     *
     * @param event
     */
    void onEvent(MessageEvent event);

    /**
     * 成功回调
     * @param result 根据泛型返回对应结果
     * @param extObject 拓展参数
     */
    void onSuccess(T result,Object extObject);
}

输出说明

MAResult 说明

参数名称 类型 描述
time long 处理时间
edgeRatio float 边缘像素比例,暂时没用
paddingW int 为提取主体,W方向padding了多少像素,一般为0
paddingH int 为提取主体,H方向padding了多少像素,一般为0
hasMA boolean 是否有主体
x1 int 左上角顶点X坐标, 默认值为0
y1 int 左上角顶点Y坐标, 默认值为0
x2 int 右上角顶点X坐标, 默认值为0
y2 int 右上角顶点Y坐标, 默认值为0
x3 int 右下角顶点X坐标, 默认值为0
y3 int 右下角顶点Y坐标, 默认值为0
x4 int 左下角顶点X坐标, 默认值为0
y4 int 左下角顶点Y坐标, 默认值为0
maBmp Bitmap 主体矫正图, 格式为ARGB_8888; 如果裁剪失败,则为null ,识别为主体后,才能返回文本矫正后的图;
corner2Src int[] 相对原图的四个角点坐标,会增加crop时的偏移量。格式为[x1, y1, x2, y2, x3, y3, x4, y4]
data byte[] 预览图byte[]数据,没用

请求示例

  1. 先初始化回调监听

```kotlin private fun initStruct() { val structParam = StructParam.Builder() .setPreviewHeight(previewHeight) // 与 TuringStruct#MStructDetect()中的图片数据宽高保持一致 .setPreviewWidth(previewWidth) .setMotionSensitivity(32) .build() TuringStruct.getInstance(this@MainActivity) .initMotionStruct(structParam, object : TuringListenerPro { override fun onSuccess(result: MAResult?, extObject: Any?) { result?.let { if (it.hasMA) { // 是否检测到主体 val points = arrayOf( PointF(it.x1.toFloat(), it.y1.toFloat()), PointF(it.x2.toFloat(), it.y2.toFloat()), PointF(it.x3.toFloat(), it.y3.toFloat()), PointF(it.x4.toFloat(), it.y4.toFloat()) )

                       // 预览界面绘制主体框
                       cameraView?.drawStruct(points,previewWidth,previewHeight,0f,0,Color.RED,5f)
                   }
               }
           }

           override fun onError(p0: Int, p1: String?) {
               Log.d(TAG, "onError code:${p0}")
           }

           override fun onEvent(event: MessageEvent?) {
               //CODE_MOTION_DETECT为检测到运动,可用此事件触发下一个流程
               if (event?.code == MessageEvent.CODE_MOTION_DETECT) {
                   Log.i(TAG, "检测到运动")
                   if (!isFingerTip) {
                       if (event.obj != null && (event.obj is Bitmap)) {
                           maBitmap = BitmapTool.copy(event.obj as Bitmap)
                           startTimer()
                       }
                   }
               }
           }
       })

} ```

  1. 客户端开发相机,处理好图片(正向+非镜像)传送给SDK进行检测

```kotlin // SDK不包含CameraView,下面给出客户端自定义相机开发调用方法示例 private fun initCamera(cameraId: Int) { cameraView = CameraView( this, binding.frameLayout.width, binding.frameLayout.height, binding.frameLayout, cameraId,"16:9", previewWidth,previewHeight,1920,1080, 0,true,180,false ) cameraView?.setOnFrameListener(object : OnFrameListener { override fun onError(code: Int, error: String?) { Log.e(TAG, "code:$code Msg:$error") }

       override fun onFrameData(data: ByteArray?, length: Int) {
           if (isInitStruct) {
               val yuvimage =
                   YuvImage(data, ImageFormat.NV21, previewWidth, previewHeight, null)
               val baos = ByteArrayOutputStream()
               yuvimage.compressToJpeg(Rect(0, 0, previewWidth, previewHeight), 100, baos)
               var mBitmap = BitmapFactory.decodeByteArray(
                   baos.toByteArray(),
                   0,
                   baos.toByteArray().size
               )
               mBitmap = BitmapUtil.rotaingImageView(180, mBitmap, 0F, 0F);//-1F, 1F镜像

               // 将处理好的图片(正向+非镜像)传给SDK
               TuringStruct.getInstance(this@MainActivity)
                   .MStructDetect(mBitmap, true, true, true)

               if (!isFingerTip) {
                   isShowPoint = false
               } else {
                   isShowPoint = true
                   fingerPro?.handDetect(mBitmap)
               }
           }
       }

       override fun onCameraEvent(event: Int) {

       }

       override fun onPicture(data: ByteArray?, length: Int) {

       }
   })

} ```

2. 同步检测

只有主体检测。

方法

/**
 * 初始化主体检测,不包括运动检测
 */
void init(TuringListener<Boolean> listener);

/**
 * 主体检测,同步方法, 配合init使用
 */
MAResult detect(Bitmap srcBmp, boolean ifCrop, boolean ifPad, boolean ifStretch);

输入说明

参数名称 类型 是否必须 描述
srcBmp Bitmap Y 图片源
ifCrop boolean Y 是否裁切并矫正主体图
ifStretch boolean Y 是否拉伸主体
ifPad boolean Y true-平板 false-台灯

输出说明

同【异步检测】->【输出说明】中 MAResult

请求示例

//1. 实例化
val turingStruct = TuringStruct.getInstance(this)

// 2. 初始化监听
var isInit = false
turingStruct.init(object :TuringListener<Boolean>{
    override fun onSuccess(result: Boolean?) {
        showToast("初始化成功")
        isInit = true
    }
    override fun onError(code: Int, message: String?) {
        isInit = false;
    }
})

//初始化成功后,根据业务需要调用主体检测方法
if (isInit){
    val result = turingStruct.detect(bitmap,true,true,true);
}

3. 资源释放

方法

void release();