feat: 增加ocr文字识别功能
5
.idea/jarRepositories.xml
generated
@ -81,5 +81,10 @@
|
|||||||
<option name="name" value="maven2" />
|
<option name="name" value="maven2" />
|
||||||
<option name="url" value="https://repo.spring.io/libs-release/" />
|
<option name="url" value="https://repo.spring.io/libs-release/" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="maven7" />
|
||||||
|
<option name="name" value="maven7" />
|
||||||
|
<option name="url" value="https://maven.aliyun.com/nexus/content/groups/public/" />
|
||||||
|
</remote-repository>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -86,6 +86,7 @@ dependencies {
|
|||||||
implementation 'androidx.navigation:navigation-fragment:2.1.0'
|
implementation 'androidx.navigation:navigation-fragment:2.1.0'
|
||||||
implementation 'androidx.navigation:navigation-ui:2.1.0'
|
implementation 'androidx.navigation:navigation-ui:2.1.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
|
implementation project(path: ':ocr')
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
|
@ -7,6 +7,7 @@ import com.kongzue.dialog.interfaces.OnDialogButtonClickListener;
|
|||||||
import com.kongzue.dialog.util.BaseDialog;
|
import com.kongzue.dialog.util.BaseDialog;
|
||||||
import com.kongzue.dialog.util.DialogSettings;
|
import com.kongzue.dialog.util.DialogSettings;
|
||||||
import com.kongzue.dialog.v3.MessageDialog;
|
import com.kongzue.dialog.v3.MessageDialog;
|
||||||
|
import com.navinfo.ocr.OCRManager;
|
||||||
import com.navinfo.outdoor.api.Constant;
|
import com.navinfo.outdoor.api.Constant;
|
||||||
import com.navinfo.outdoor.api.UserApplication;
|
import com.navinfo.outdoor.api.UserApplication;
|
||||||
import com.navinfo.outdoor.base.BaseActivity;
|
import com.navinfo.outdoor.base.BaseActivity;
|
||||||
@ -115,7 +116,8 @@ public class HomeActivity extends BaseActivity {
|
|||||||
|
|
||||||
// 注册位置更新的lifeCycle
|
// 注册位置更新的lifeCycle
|
||||||
getLifecycle().addObserver(LocationLifeCycle.getInstance());
|
getLifecycle().addObserver(LocationLifeCycle.getInstance());
|
||||||
|
// 初始化图像识别组件
|
||||||
|
OCRManager.Companion.getInstance().init(HomeActivity.this);
|
||||||
} else {
|
} else {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
@ -29,15 +29,20 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
import com.elvishew.xlog.XLog;
|
||||||
import com.github.lazylibrary.util.FileUtils;
|
import com.github.lazylibrary.util.FileUtils;
|
||||||
import com.kongzue.dialog.interfaces.OnDialogButtonClickListener;
|
import com.kongzue.dialog.interfaces.OnDialogButtonClickListener;
|
||||||
import com.kongzue.dialog.util.BaseDialog;
|
import com.kongzue.dialog.util.BaseDialog;
|
||||||
import com.kongzue.dialog.util.DialogSettings;
|
import com.kongzue.dialog.util.DialogSettings;
|
||||||
import com.kongzue.dialog.v3.MessageDialog;
|
import com.kongzue.dialog.v3.MessageDialog;
|
||||||
|
import com.navinfo.ocr.OCRManager;
|
||||||
|
import com.navinfo.ocr.model.OcrViewResultModel;
|
||||||
import com.navinfo.outdoor.R;
|
import com.navinfo.outdoor.R;
|
||||||
import com.navinfo.outdoor.api.Constant;
|
import com.navinfo.outdoor.api.Constant;
|
||||||
import com.navinfo.outdoor.api.UserApplication;
|
import com.navinfo.outdoor.api.UserApplication;
|
||||||
import com.navinfo.outdoor.base.BaseActivity;
|
import com.navinfo.outdoor.base.BaseActivity;
|
||||||
|
import com.navinfo.outdoor.bean.LocationRecorder;
|
||||||
|
import com.navinfo.outdoor.util.BitmapUtil;
|
||||||
import com.navinfo.outdoor.util.GPSUtils;
|
import com.navinfo.outdoor.util.GPSUtils;
|
||||||
import com.navinfo.outdoor.util.Geohash;
|
import com.navinfo.outdoor.util.Geohash;
|
||||||
import com.navinfo.outdoor.util.GeometryTools;
|
import com.navinfo.outdoor.util.GeometryTools;
|
||||||
@ -51,6 +56,7 @@ import com.navinfo.outdoor.util.ToastUtils;
|
|||||||
import com.otaliastudios.cameraview.CameraListener;
|
import com.otaliastudios.cameraview.CameraListener;
|
||||||
import com.otaliastudios.cameraview.CameraLogger;
|
import com.otaliastudios.cameraview.CameraLogger;
|
||||||
import com.otaliastudios.cameraview.CameraOptions;
|
import com.otaliastudios.cameraview.CameraOptions;
|
||||||
|
import com.otaliastudios.cameraview.CameraUtils;
|
||||||
import com.otaliastudios.cameraview.CameraView;
|
import com.otaliastudios.cameraview.CameraView;
|
||||||
import com.otaliastudios.cameraview.FileCallback;
|
import com.otaliastudios.cameraview.FileCallback;
|
||||||
import com.otaliastudios.cameraview.PictureResult;
|
import com.otaliastudios.cameraview.PictureResult;
|
||||||
@ -82,13 +88,16 @@ import org.locationtech.jts.geom.MultiLineString;
|
|||||||
import com.wanghong.webpnative.WebPNative;
|
import com.wanghong.webpnative.WebPNative;
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.reactivestreams.Subscription;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
@ -96,12 +105,21 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import static com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE;
|
import static com.tencent.tencentmap.mapsdk.maps.model.MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE;
|
||||||
|
|
||||||
|
import io.reactivex.BackpressureStrategy;
|
||||||
|
import io.reactivex.Flowable;
|
||||||
|
import io.reactivex.FlowableEmitter;
|
||||||
|
import io.reactivex.FlowableOnSubscribe;
|
||||||
|
import io.reactivex.FlowableSubscriber;
|
||||||
|
import io.reactivex.Notification;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.ObservableEmitter;
|
import io.reactivex.ObservableEmitter;
|
||||||
import io.reactivex.ObservableOnSubscribe;
|
import io.reactivex.ObservableOnSubscribe;
|
||||||
import io.reactivex.Observer;
|
import io.reactivex.Observer;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
|
import io.reactivex.functions.BiFunction;
|
||||||
|
import io.reactivex.functions.Consumer;
|
||||||
|
import io.reactivex.functions.Function;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,12 +136,14 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
private String finalVideoPath, geoWkt, detail; // 摄像后最终保存的文件名
|
private String finalVideoPath, geoWkt, detail; // 摄像后最终保存的文件名
|
||||||
private ViewGroup layerChange; // 切换地图和相机的父控件
|
private ViewGroup layerChange; // 切换地图和相机的父控件
|
||||||
private CheckBox capturePicture; //拍照
|
private CheckBox capturePicture; //拍照
|
||||||
private File paperFile, logFile;
|
private File paperFile, logFile, checkFile/*辅助检查文件*/;
|
||||||
private ImageView ivZoomAdd, ivZoomDel, ivLocation, ivPicRoadImage, ivPicVideoImage, imageView;
|
private ImageView ivZoomAdd, ivZoomDel, ivLocation, ivPicRoadImage, ivPicVideoImage, imageView;
|
||||||
private View layerMapController;
|
private View layerMapController;
|
||||||
private MyLocation oldCurrentLocation = null;
|
private MyLocation oldCurrentLocation = null;
|
||||||
private Timer timer;
|
// private Timer timer;
|
||||||
private TimerTask timerTask;
|
// private TimerTask timerTask;
|
||||||
|
private Disposable disposable; // RxJava循环拍照的控制对象
|
||||||
|
private FlowableEmitter<PictureResult> pictureEmitter; // RxJava控制照片生成
|
||||||
private SystemTTS systemTTS;
|
private SystemTTS systemTTS;
|
||||||
private StringBuilder picturesBuilder;
|
private StringBuilder picturesBuilder;
|
||||||
private LatLng startLatLine, endLatLine;
|
private LatLng startLatLine, endLatLine;
|
||||||
@ -145,10 +165,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
private Handler handler = new Handler(new Handler.Callback() {
|
private Handler handler = new Handler(new Handler.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public boolean handleMessage(@NonNull Message msg) {
|
public boolean handleMessage(@NonNull Message msg) {
|
||||||
if (msg.what == 0x101) {
|
if (msg.what == 0x102) {
|
||||||
System.out.println("收到拍照按钮请求");
|
|
||||||
camera.takePictureSnapshot();
|
|
||||||
} else if (msg.what == 0x102) {
|
|
||||||
if (imageView != null) {
|
if (imageView != null) {
|
||||||
imageView.setEnabled(true);
|
imageView.setEnabled(true);
|
||||||
}
|
}
|
||||||
@ -157,7 +174,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
capturePicture.setText("开始采集");
|
capturePicture.setText("开始采集");
|
||||||
}
|
}
|
||||||
capturePicture.setChecked(false);
|
capturePicture.setChecked(false);
|
||||||
stopTimer();
|
stopTakePhoto();
|
||||||
} else if (msg.what == 0x104) {
|
} else if (msg.what == 0x104) {
|
||||||
tvConvert.setText("转换成功:"+(++msg.arg1));
|
tvConvert.setText("转换成功:"+(++msg.arg1));
|
||||||
}
|
}
|
||||||
@ -207,12 +224,8 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
if (finalVideoPath != null) {
|
if (finalVideoPath != null) {
|
||||||
File file = new File(finalVideoPath);
|
File file = new File(finalVideoPath);
|
||||||
paperFile = new File(Objects.requireNonNull(file.getParentFile()).getAbsoluteFile() + "/" + "paper.txt");
|
paperFile = new File(Objects.requireNonNull(file.getParentFile()).getAbsoluteFile() + "/" + "paper.txt");
|
||||||
|
checkFile = new File(Objects.requireNonNull(file.getParentFile()).getAbsoluteFile() + "/" + "check.json");
|
||||||
videoIndex = Integer.parseInt(file.getName().replace(".webp", ""));
|
videoIndex = Integer.parseInt(file.getName().replace(".webp", ""));
|
||||||
if (videoIndex == 0) {
|
|
||||||
videoIndex = -1;
|
|
||||||
} else {
|
|
||||||
videoIndex = videoIndex - 1;
|
|
||||||
}
|
|
||||||
convertIndex = videoIndex;
|
convertIndex = videoIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,31 +263,25 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
radioGroupPicture.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
|
radioGroupPicture.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||||
|
stopTakePhoto();
|
||||||
|
capturePicture.setChecked(false);
|
||||||
switch (checkedId) {
|
switch (checkedId) {
|
||||||
case R.id.radio_btn_hand://手动
|
case R.id.radio_btn_hand://手动
|
||||||
radioPicture = 1;
|
radioPicture = 1;
|
||||||
isOration = false;
|
isOration = false;
|
||||||
capturePicture.setText("拍摄");
|
capturePicture.setText("拍摄");
|
||||||
capturePicture.setChecked(false);
|
|
||||||
stopTimer();
|
|
||||||
break;
|
break;
|
||||||
case R.id.radio_btn_auto://自动1秒:
|
case R.id.radio_btn_auto://自动1秒:
|
||||||
radioPicture = 2;
|
radioPicture = 2;
|
||||||
capturePicture.setText("开始采集");
|
capturePicture.setText("开始采集");
|
||||||
capturePicture.setChecked(false);
|
|
||||||
stopTimer();
|
|
||||||
break;
|
break;
|
||||||
case R.id.radio_btn_auto_sec://自动2 秒
|
case R.id.radio_btn_auto_sec://自动2 秒
|
||||||
radioPicture = 3;
|
radioPicture = 3;
|
||||||
capturePicture.setText("开始采集");
|
capturePicture.setText("开始采集");
|
||||||
capturePicture.setChecked(false);
|
|
||||||
stopTimer();
|
|
||||||
break;
|
break;
|
||||||
case R.id.radio_btn_half_sec://自动0.5 秒
|
case R.id.radio_btn_half_sec://自动0.5 秒
|
||||||
radioPicture = 4;
|
radioPicture = 4;
|
||||||
capturePicture.setText("开始采集");
|
capturePicture.setText("开始采集");
|
||||||
capturePicture.setChecked(false);
|
|
||||||
stopTimer();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,13 +321,14 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
} else {
|
} else {
|
||||||
picturesBuilder.append(TimestampUtil.time()).append(",").append("capturePicture 点击了拍摄 ,");
|
picturesBuilder.append(TimestampUtil.time()).append(",").append("capturePicture 点击了拍摄 ,");
|
||||||
}
|
}
|
||||||
startTimer();
|
startTakePhoto(radioPicture);
|
||||||
|
startTakePhoto(radioPicture);
|
||||||
} else {
|
} else {
|
||||||
if (radioPicture != 1) {
|
if (radioPicture != 1) {
|
||||||
capturePicture.setText("开始采集");
|
capturePicture.setText("开始采集");
|
||||||
picturesBuilder.append(TimestampUtil.time()).append(",").append("capturePicture 点击了暂停采集 ,");
|
picturesBuilder.append(TimestampUtil.time()).append(",").append("capturePicture 点击了暂停采集 ,");
|
||||||
}
|
}
|
||||||
stopTimer();
|
stopTakePhoto();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -382,6 +390,96 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Flowable<PictureResult> pictureResultFlowable = Flowable.create(new FlowableOnSubscribe<PictureResult>() {
|
||||||
|
@Override
|
||||||
|
public void subscribe(FlowableEmitter<PictureResult> emitter) throws Exception {
|
||||||
|
pictureEmitter = emitter;
|
||||||
|
}
|
||||||
|
}, BackpressureStrategy.BUFFER).subscribeOn(Schedulers.io());
|
||||||
|
|
||||||
|
Flowable<Integer> integerFlowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
|
||||||
|
@Override
|
||||||
|
public void subscribe(FlowableEmitter<Integer> emitter) {
|
||||||
|
for (int i = videoIndex; ; i++) { // 标记当前是第几个图片,记录Index
|
||||||
|
emitter.onNext(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, BackpressureStrategy.BUFFER).subscribeOn(Schedulers.io());
|
||||||
|
|
||||||
|
Flowable.zip(pictureResultFlowable, integerFlowable, new BiFunction<PictureResult, Integer, Map>(){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> apply(PictureResult pictureResult, Integer fileIndex) throws Exception { // 将图片转为File文件
|
||||||
|
// 图片和paper.txt处理
|
||||||
|
File currentFile = new File(paperFile.getParentFile().getAbsolutePath() + "/" + fileIndex + ".webp");
|
||||||
|
CameraUtils.writeToFile(pictureResult.getData(), currentFile); // 生成照片文件
|
||||||
|
// 记录当前点位信息
|
||||||
|
LocationRecorder recorder = new LocationRecorder();
|
||||||
|
recorder.setTime(System.currentTimeMillis());
|
||||||
|
// 记录主定位方式
|
||||||
|
recorder.setTencentLocationX(LocationLifeCycle.getInstance().getMainLocation().getLongitude());
|
||||||
|
recorder.setTencentLocationY(LocationLifeCycle.getInstance().getMainLocation().getLatitude());
|
||||||
|
// 记录辅助定位方式
|
||||||
|
MyLocation gpsLocation = LocationLifeCycle.getInstance().getReferenceLocation();
|
||||||
|
if (gpsLocation!=null) {
|
||||||
|
recorder.setGpsLocationX(gpsLocation.getLongitude());
|
||||||
|
recorder.setGpsLocationY(gpsLocation.getLatitude());
|
||||||
|
}
|
||||||
|
recorder.setBearing(LocationLifeCycle.getInstance().getMainLocation().getBearing());
|
||||||
|
recorder.setRssi(GPSUtils.getInstance(PicturesActivity.this).getSateliteCount());
|
||||||
|
recorder.setSatelliteCount(GPSUtils.getInstance(PicturesActivity.this).getSateliteCount());
|
||||||
|
FileUtils.writeFile(paperFile.getAbsolutePath(), recorder.toString(formatter, fileIndex), true);
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("index", fileIndex);
|
||||||
|
map.put("picture", pictureResult);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.subscribeOn(Schedulers.io()) // 指定上游为IO线程
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.doOnNext(new Consumer<Map>() {
|
||||||
|
@Override
|
||||||
|
public void accept(Map map) throws Exception {
|
||||||
|
// 绘制图标
|
||||||
|
initMarker(booleanExtra);
|
||||||
|
// 设置主界面拍照个数显示
|
||||||
|
tvTitle.setText(Integer.parseInt(map.get("index").toString())+"");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.observeOn(Schedulers.computation())// 开始进行图片辅助判定
|
||||||
|
.subscribe(new FlowableSubscriber<Map>() {
|
||||||
|
@Override
|
||||||
|
public void onSubscribe(Subscription s) {
|
||||||
|
s.request(Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNext(Map map) {
|
||||||
|
int index = Integer.parseInt(map.get("index").toString());
|
||||||
|
PictureResult pictureResult = (PictureResult) map.get("picture");
|
||||||
|
// 记录当前完成多少个图片的处理
|
||||||
|
// 开始ocr文字识别
|
||||||
|
List<OcrViewResultModel> ocrViewResultModels = OCRManager.Companion.getInstance().ocr(BitmapUtil.getBitmapFromBytes(pictureResult.getData()));
|
||||||
|
if (ocrViewResultModels!=null&&!ocrViewResultModels.isEmpty()) {
|
||||||
|
// 该照片存在文字信息,获取占比最大的文字,为后续POI判定做准备
|
||||||
|
}
|
||||||
|
// 获取当前手机姿态,判定该照片手机姿态是否合格
|
||||||
|
float yDegree = sensorOritationLifecycle.getYDegree();
|
||||||
|
// 周边搜索,判定周边POI是否存在
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
camera.addCameraListener(new CameraListener() {
|
camera.addCameraListener(new CameraListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onPictureTaken(@NonNull PictureResult result) {
|
public void onPictureTaken(@NonNull PictureResult result) {
|
||||||
@ -389,44 +487,29 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
super.onPictureTaken(result);
|
super.onPictureTaken(result);
|
||||||
System.out.println("收到拍照按钮jieguo:"+result.getSize().toString());
|
System.out.println("收到拍照按钮jieguo:"+result.getSize().toString());
|
||||||
isBack = true;
|
isBack = true;
|
||||||
// 如果当前手机是竖向,则不
|
// 如果当前手机是竖向,则不允许拍照
|
||||||
if (isOration) {
|
if (Objects.requireNonNull(camera.getPictureSize()).getWidth() < camera.getPictureSize().getHeight()) {
|
||||||
if (Objects.requireNonNull(camera.getPictureSize()).getWidth() < camera.getPictureSize().getHeight()) {
|
isOration = true;
|
||||||
isOration = true;
|
ToastUtils.Message(PicturesActivity.this, "不允许竖向拍摄...");
|
||||||
ToastUtils.Message(PicturesActivity.this, "不允许竖向拍摄...");
|
picturesBuilder.append("camera 用户竖屏拍照 ,");
|
||||||
picturesBuilder.append("camera 用户竖屏拍照 ,");
|
stopTakePhoto();
|
||||||
stopTimer();
|
capturePicture.setChecked(false);
|
||||||
|
if (radioPicture != 1) {
|
||||||
|
capturePicture.setText("开始采集");
|
||||||
capturePicture.setChecked(false);
|
capturePicture.setChecked(false);
|
||||||
if (radioPicture != 1) {
|
|
||||||
capturePicture.setText("开始采集");
|
|
||||||
capturePicture.setChecked(false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
isOration = false;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
isOration = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = new File(finalVideoPath);
|
if (pictureEmitter!=null) {
|
||||||
synchronized (finalVideoPath) {
|
pictureEmitter.onNext(result);
|
||||||
// 生成点位marker
|
|
||||||
initMarker(booleanExtra);
|
|
||||||
result.toFile(file, new FileCallback() {
|
|
||||||
@Override
|
|
||||||
public void onFileReady(@Nullable File file) {
|
|
||||||
int currentIndex = videoIndex = Integer.parseInt(file.getName().replace(".webp", ""));
|
|
||||||
// 下一张照片的路径
|
|
||||||
finalVideoPath = Objects.requireNonNull(file.getParentFile()).getAbsolutePath() + "/" + (videoIndex + 1) + ".webp";
|
|
||||||
tvTitle.setText("拍摄成功:" + (videoIndex + 1));
|
|
||||||
|
|
||||||
UserApplication.fixedThreadPool.execute(new Jpg2WebpRunnable(/*result, */file, 0, booleanExtra, currentIndex));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
isBack = false;
|
isBack = false;
|
||||||
if (isOration) {
|
if (isOration) {
|
||||||
stopTimer();
|
stopTakePhoto();
|
||||||
}
|
}
|
||||||
if (radioPicture != 1) {
|
if (radioPicture != 1) {
|
||||||
capturePicture.setText("开始采集");
|
capturePicture.setText("开始采集");
|
||||||
@ -441,18 +524,6 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
layoutParamsMap.height = dm.widthPixels / 3;
|
layoutParamsMap.height = dm.widthPixels / 3;
|
||||||
layoutParamsMap.width = dm.heightPixels / 3;
|
layoutParamsMap.width = dm.heightPixels / 3;
|
||||||
tvMapView.setLayoutParams(layoutParamsMap);
|
tvMapView.setLayoutParams(layoutParamsMap);
|
||||||
timerTask = new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (radioPicture == 1) {
|
|
||||||
camera.takePictureSnapshot();
|
|
||||||
} else {
|
|
||||||
Message message = new Message();
|
|
||||||
message.what = 0x101;
|
|
||||||
handler.sendMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Button btnSetting = findViewById(R.id.btn_setting);
|
Button btnSetting = findViewById(R.id.btn_setting);
|
||||||
btnSetting.setOnClickListener(new View.OnClickListener() {
|
btnSetting.setOnClickListener(new View.OnClickListener() {
|
||||||
@ -484,7 +555,6 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (file.exists() && file != null) {
|
if (file.exists() && file != null) {
|
||||||
// if (initWeb(file, count, isBoolean, index)) {
|
|
||||||
initMarkerPaper(index);
|
initMarkerPaper(index);
|
||||||
if (PicturesActivity.this != null&&handler != null) {
|
if (PicturesActivity.this != null&&handler != null) {
|
||||||
if (radioPicture == 1) {
|
if (radioPicture == 1) {
|
||||||
@ -498,18 +568,10 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
handler.sendMessage(message);
|
handler.sendMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// runOnUiThread(new Runnable() {
|
|
||||||
// @SuppressLint("SetTextI18n")
|
|
||||||
// @Override
|
|
||||||
// public void run() {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
} else {
|
} else {
|
||||||
isBack = false;
|
isBack = false;
|
||||||
if (isOration) {
|
if (isOration) {
|
||||||
stopTimer();
|
stopTakePhoto();
|
||||||
}
|
}
|
||||||
if (radioPicture != 1) {
|
if (radioPicture != 1) {
|
||||||
capturePicture.setText("开始采集");
|
capturePicture.setText("开始采集");
|
||||||
@ -525,32 +587,6 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean initWeb(File file, int count, boolean isBoolean, int index) {
|
|
||||||
try {
|
|
||||||
count++;
|
|
||||||
WebPNative webPNative = new WebPNative();
|
|
||||||
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
|
|
||||||
webPNative.encodeRGBA(bitmap, file.getPath(), 90);
|
|
||||||
if (!bitmap.isRecycled()) {
|
|
||||||
bitmap.recycle();
|
|
||||||
}
|
|
||||||
initMarkerPaper(index);
|
|
||||||
return true;
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
//如果是写入txt记录失败,上传失败记录
|
|
||||||
UMCrashManager.reportCrash(this, e);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
UMCrashManager.reportCrash(this, e);
|
|
||||||
if (count < 3) {
|
|
||||||
//当尝试次数小于3次,则加入转换队列,尝试重新转换
|
|
||||||
UserApplication.fixedThreadPool.execute(new Jpg2WebpRunnable(/*result, */file, count, isBoolean, index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initLine() {
|
private void initLine() {
|
||||||
if (geoWkt != null) {
|
if (geoWkt != null) {
|
||||||
List<LineString> lineStringList = new ArrayList<>();
|
List<LineString> lineStringList = new ArrayList<>();
|
||||||
@ -871,7 +907,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
picturesBuilder.append(TimestampUtil.time()).append(",").append("onPause ,");
|
picturesBuilder.append(TimestampUtil.time()).append(",").append("onPause ,");
|
||||||
tvMapView.onPause();
|
tvMapView.onPause();
|
||||||
camera.close();
|
camera.close();
|
||||||
stopTimer();
|
stopTakePhoto();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -887,7 +923,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
camera.destroy();
|
camera.destroy();
|
||||||
tvMapView.onDestroy();
|
tvMapView.onDestroy();
|
||||||
systemTTS.stopSpeak();
|
systemTTS.stopSpeak();
|
||||||
stopTimer();
|
stopTakePhoto();
|
||||||
if (polyline != null) {
|
if (polyline != null) {
|
||||||
polyline.remove();
|
polyline.remove();
|
||||||
}
|
}
|
||||||
@ -911,21 +947,6 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Subscribe(threadMode = ThreadMode.MAIN)
|
|
||||||
// public void onEventMessageMainThread(Message msg) {
|
|
||||||
// if (msg.what == Constant.EVENT_WHAT_LOCATION_CHANGE) { // 用户位置更新
|
|
||||||
// if (tencentMap != null && !isMapSlide) {
|
|
||||||
// TencentLocation tencentLocation = (TencentLocation) msg.obj;
|
|
||||||
// CameraUpdate cameraSigma = CameraUpdateFactory.newCameraPosition(new CameraPosition(
|
|
||||||
// new LatLng(tencentLocation.getLatitude(), tencentLocation.getLongitude()), //中心点坐标,地图目标经纬度
|
|
||||||
// 17, //目标缩放级别
|
|
||||||
// 0, //目标倾斜角
|
|
||||||
// tencentLocation.getBearing())); //目标旋转角 0~360° (正北方为0)
|
|
||||||
// tencentMap.animateCamera(cameraSigma);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
public void initMarkerPaper(int index) {
|
public void initMarkerPaper(int index) {
|
||||||
@ -1096,7 +1117,7 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
Observable.create(new ObservableOnSubscribe<String>() {
|
Observable.create(new ObservableOnSubscribe<String>() {
|
||||||
@Override
|
@Override
|
||||||
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
|
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
|
||||||
stopTimer();
|
stopTakePhoto();
|
||||||
handler.removeMessages(0x101); // 如果handler中存在缓存的拍摄请求,也清空
|
handler.removeMessages(0x101); // 如果handler中存在缓存的拍摄请求,也清空
|
||||||
picturesBuilder.append(TimestampUtil.time()).append(",").append("onClick 点击了结束采集 ,");
|
picturesBuilder.append(TimestampUtil.time()).append(",").append("onClick 点击了结束采集 ,");
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
@ -1150,48 +1171,26 @@ public class PicturesActivity extends BaseActivity implements View.OnClickListen
|
|||||||
removables.add(marker);
|
removables.add(marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startTimer() {
|
private void startTakePhoto(int radioPicture) {
|
||||||
if (timer == null) {
|
|
||||||
timer = new Timer();
|
|
||||||
}
|
|
||||||
if (timerTask == null) {
|
|
||||||
timerTask = new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (handler!=null) {
|
|
||||||
if (radioPicture == 1) {
|
|
||||||
camera.takePictureSnapshot();
|
|
||||||
} else {
|
|
||||||
Message message = new Message();
|
|
||||||
message.what = 0x101;
|
|
||||||
handler.sendMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (radioPicture == 1) {
|
if (radioPicture == 1) {
|
||||||
timer.schedule(timerTask, 0);
|
camera.takePictureSnapshot();
|
||||||
} else if (radioPicture == 2) {
|
} else {
|
||||||
timer.schedule(timerTask, 0, 1000);
|
disposable = Observable.interval(1000L, TimeUnit.MILLISECONDS, Schedulers.io())
|
||||||
} else if (radioPicture == 3) {
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
timer.schedule(timerTask, 0, 2000);
|
.subscribe(new Consumer<Long>() {
|
||||||
} else if (radioPicture == 4) {
|
@Override
|
||||||
timer.schedule(timerTask, 0, 500);
|
public void accept(Long aLong) throws Exception {
|
||||||
|
camera.takePictureSnapshot();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopTimer() {
|
private void stopTakePhoto() {
|
||||||
if (timer != null) {
|
if (disposable!=null&&!disposable.isDisposed()) {
|
||||||
timer.cancel();
|
disposable.dispose();
|
||||||
timer = null;
|
|
||||||
}
|
|
||||||
if (timerTask != null) {
|
|
||||||
timerTask.cancel();
|
|
||||||
timerTask = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置当前界面亮度
|
// 设置当前界面亮度
|
||||||
private void setWindowBrightness(int brightness) {
|
private void setWindowBrightness(int brightness) {
|
||||||
// Window window = getWindow();
|
// Window window = getWindow();
|
||||||
|
@ -79,7 +79,7 @@ public class StaySubmitFragment extends BaseFragment implements View.OnClickList
|
|||||||
private CheckBox cbSelect;
|
private CheckBox cbSelect;
|
||||||
private File logFile;
|
private File logFile;
|
||||||
private StringBuilder staySubmitBuilder;
|
private StringBuilder staySubmitBuilder;
|
||||||
private Logger logger = XLogUtils.Companion.getInstance().getUploadLogWriter();
|
private Logger logger;
|
||||||
|
|
||||||
public static StaySubmitFragment newInstance(Bundle bundle) {
|
public static StaySubmitFragment newInstance(Bundle bundle) {
|
||||||
StaySubmitFragment fragment = new StaySubmitFragment();
|
StaySubmitFragment fragment = new StaySubmitFragment();
|
||||||
@ -93,6 +93,7 @@ public class StaySubmitFragment extends BaseFragment implements View.OnClickList
|
|||||||
if (!EventBus.getDefault().isRegistered(this)) {//加上判断
|
if (!EventBus.getDefault().isRegistered(this)) {//加上判断
|
||||||
EventBus.getDefault().register(this);
|
EventBus.getDefault().register(this);
|
||||||
}
|
}
|
||||||
|
logger=XLogUtils.Companion.getInstance().getUploadLogWriter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
1691
app/src/main/java/com/navinfo/outdoor/util/BitmapUtil.java
Normal file
@ -13,10 +13,9 @@ buildscript {
|
|||||||
maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'}
|
maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'}
|
||||||
maven{ url 'https://maven.aliyun.com/repository/public'}
|
maven{ url 'https://maven.aliyun.com/repository/public'}
|
||||||
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
|
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
|
||||||
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
|
maven{ url 'https://maven.aliyun.com/nexus/content/groups/public/'}
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
maven { url "https://repo.spring.io/libs-release/" }
|
maven { url "https://repo.spring.io/libs-release/" }
|
||||||
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
|
|
||||||
//友盟 检测bug
|
//友盟 检测bug
|
||||||
maven { url 'https://repo1.maven.org/maven2/' }
|
maven { url 'https://repo1.maven.org/maven2/' }
|
||||||
jcenter()
|
jcenter()
|
||||||
@ -27,7 +26,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.2.2'
|
classpath 'com.android.tools.build:gradle:7.0.0'
|
||||||
//对kotlin支持
|
//对kotlin支持
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
@ -48,10 +47,9 @@ allprojects {
|
|||||||
maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'}
|
maven{ url 'https://maven.aliyun.com/repository/gradle-plugin'}
|
||||||
maven{ url 'https://maven.aliyun.com/repository/public'}
|
maven{ url 'https://maven.aliyun.com/repository/public'}
|
||||||
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
|
maven{ url 'https://maven.aliyun.com/repository/jcenter'}
|
||||||
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
|
maven{ url 'https://maven.aliyun.com/nexus/content/groups/public/'}
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
maven { url "https://repo.spring.io/libs-release/" }
|
maven { url "https://repo.spring.io/libs-release/" }
|
||||||
maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
|
|
||||||
//友盟 检测bug
|
//友盟 检测bug
|
||||||
maven { url 'https://repo1.maven.org/maven2/' }
|
maven { url 'https://repo1.maven.org/maven2/' }
|
||||||
jcenter()
|
jcenter()
|
||||||
|
6
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Tue May 25 11:18:32 CST 2021
|
#Mon Mar 20 10:38:13 CST 2023
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
1
ocr/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
61
ocr/build.gradle
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
plugins {
|
||||||
|
id 'com.android.library'
|
||||||
|
id 'org.jetbrains.kotlin.android'
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace 'com.navinfo.ocr'
|
||||||
|
compileSdk 31
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk 23
|
||||||
|
targetSdk 30
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
ndk {
|
||||||
|
abiFilters "armeabi", "armeabi-v7a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
debug {
|
||||||
|
packagingOptions {
|
||||||
|
doNotStrip '**/*.so' // 避免so资源文件编译提示,可忽略
|
||||||
|
}
|
||||||
|
}
|
||||||
|
release {
|
||||||
|
packagingOptions {
|
||||||
|
doNotStrip '**/*.so' // 避免so资源文件编译提示,可忽略
|
||||||
|
}
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = '1.8'
|
||||||
|
}
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
jniLibs.srcDirs = ['libs']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
|
implementation 'com.google.android.material:material:1.8.0'
|
||||||
|
testImplementation 'junit:junit:4.13.2'
|
||||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||||
|
api files('libs/easyedge-sdk.jar')
|
||||||
|
}
|
BIN
ocr/libs/arm64-v8a/libc++_shared.so
Normal file
BIN
ocr/libs/arm64-v8a/libedge-infer.so
Normal file
BIN
ocr/libs/armeabi-v7a/libc++_shared.so
Normal file
BIN
ocr/libs/armeabi-v7a/libedge-infer.so
Normal file
BIN
ocr/libs/easyedge-sdk.jar
Normal file
21
ocr/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.navinfo.ocr
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
fun useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
assertEquals("com.navinfo.ocr", appContext.packageName)
|
||||||
|
}
|
||||||
|
}
|
8
ocr/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<!-- <application-->
|
||||||
|
<!-- android:allowBackup="true"-->
|
||||||
|
<!-- />-->
|
||||||
|
|
||||||
|
</manifest>
|
26
ocr/src/main/assets/infer/infer_cfg.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"framework": "fluid",
|
||||||
|
"model_info": {
|
||||||
|
"n_type": 0,
|
||||||
|
"best_threshold": 0.1,
|
||||||
|
"model_kind": 100
|
||||||
|
},
|
||||||
|
"pre_process": {
|
||||||
|
"mean": [123.675, 116.28, 103.53],
|
||||||
|
"scale": [
|
||||||
|
0.01712475383166,
|
||||||
|
0.01750700280112,
|
||||||
|
0.01742919389978
|
||||||
|
],
|
||||||
|
"color_format": "BGR",
|
||||||
|
"channel_order": "CHW",
|
||||||
|
"resize": [960, 960],
|
||||||
|
"rescale_mode": "keep_ratio",
|
||||||
|
"max_size":960,
|
||||||
|
"ocr_rec_resize": [320,32]
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"fluid": {"optType": "nb"}
|
||||||
|
}
|
||||||
|
}
|
6624
ocr/src/main/assets/infer/label_list.txt
Normal file
BIN
ocr/src/main/assets/infer/model
Normal file
BIN
ocr/src/main/assets/infer/params
Normal file
2
ocr/src/main/assets/symbols/square.svg
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1659598895605" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3308" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
|
||||||
|
</style></defs><path d="M885.333333 938.666667H138.666667a53.393333 53.393333 0 0 1-53.333334-53.333334V138.666667a53.393333 53.393333 0 0 1 53.333334-53.333334h746.666666a53.393333 53.393333 0 0 1 53.333334 53.333334v746.666666a53.393333 53.393333 0 0 1-53.333334 53.333334zM138.666667 128a10.666667 10.666667 0 0 0-10.666667 10.666667v746.666666a10.666667 10.666667 0 0 0 10.666667 10.666667h746.666666a10.666667 10.666667 0 0 0 10.666667-10.666667V138.666667a10.666667 10.666667 0 0 0-10.666667-10.666667z" fill="#A1DBF5" p-id="3309"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
209
ocr/src/main/java/com/navinfo/ocr/OCRManager.kt
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
package com.navinfo.ocr
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.os.Build
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
import com.baidu.ai.edge.core.base.CallException
|
||||||
|
import com.baidu.ai.edge.core.base.Consts
|
||||||
|
import com.baidu.ai.edge.core.infer.InferConfig
|
||||||
|
import com.baidu.ai.edge.core.infer.InferManager
|
||||||
|
import com.baidu.ai.edge.core.ocr.OcrInterface
|
||||||
|
import com.baidu.ai.edge.core.ocr.OcrResultModel
|
||||||
|
import com.baidu.ai.edge.core.util.FileUtil
|
||||||
|
import com.navinfo.ocr.model.OcrViewResultModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.MainScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class OCRManager {
|
||||||
|
private var mContext: Context? = null
|
||||||
|
private var modelName = ""
|
||||||
|
private val socList = ArrayList<String>()
|
||||||
|
private var modelType = 0
|
||||||
|
private var soc: String? = null
|
||||||
|
private var mOcrManager: OcrInterface? = null
|
||||||
|
private val CONFIDENCE = 0.3f
|
||||||
|
|
||||||
|
fun ocr(bitmap: Bitmap): List<OcrViewResultModel> {
|
||||||
|
Log.e("jingo", "OCRManager 线程名称3 ${Thread.currentThread().name}")
|
||||||
|
val list = ArrayList<OcrViewResultModel>()
|
||||||
|
if (mOcrManager != null) {
|
||||||
|
val modelList = mOcrManager!!.ocr(bitmap, CONFIDENCE)
|
||||||
|
for (i in modelList.indices) {
|
||||||
|
val mOcrResultModel: OcrResultModel = modelList[i]
|
||||||
|
val mOcrViewResultModel = OcrViewResultModel()
|
||||||
|
mOcrViewResultModel.colorId = mOcrResultModel.labelIndex
|
||||||
|
mOcrViewResultModel.index = i + 1
|
||||||
|
mOcrViewResultModel.confidence = mOcrResultModel.confidence
|
||||||
|
mOcrViewResultModel.name = mOcrResultModel.label
|
||||||
|
mOcrViewResultModel.bounds = mOcrResultModel.points
|
||||||
|
mOcrViewResultModel.isTextOverlay = true
|
||||||
|
list.add(mOcrViewResultModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原有的
|
||||||
|
*/
|
||||||
|
private fun initConfigFromDemoConfig(): Boolean {
|
||||||
|
val confJson =
|
||||||
|
FileUtil.readAssetsFileUTF8StringIfExists(mContext!!.assets, "demo/config.json")
|
||||||
|
if (TextUtils.isEmpty(confJson)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val confObj = JSONObject(confJson)
|
||||||
|
modelName = confObj.optString("modelName", "")
|
||||||
|
val str = confObj.optString("soc", Consts.SOC_ARM)
|
||||||
|
val socs = str.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
socList.addAll(listOf(*socs))
|
||||||
|
modelType = confObj.getInt("modelType")
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开放模型
|
||||||
|
*/
|
||||||
|
private fun initConfigFromDemoConf(): Boolean {
|
||||||
|
val confJson =
|
||||||
|
FileUtil.readAssetsFileUTF8StringIfExists(mContext!!.assets, "demo/conf.json")
|
||||||
|
if (TextUtils.isEmpty(confJson)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val confObj = JSONObject(confJson)
|
||||||
|
modelName = confObj.optString("modelName", "")
|
||||||
|
socList.add(Consts.SOC_ARM)
|
||||||
|
val inferCfgJson = FileUtil.readAssetsFileUTF8StringIfExists(
|
||||||
|
mContext!!.assets,
|
||||||
|
Consts.ASSETS_DIR_ARM + "/infer_cfg.json"
|
||||||
|
)
|
||||||
|
if (TextUtils.isEmpty(inferCfgJson)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val inferCfgObj = JSONObject(inferCfgJson)
|
||||||
|
modelType = inferCfgObj.getJSONObject("model_info").getInt("model_kind")
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkChip(): Boolean {
|
||||||
|
if (socList.contains(Consts.SOC_DSP) && Build.HARDWARE.equals("qcom", ignoreCase = true)) {
|
||||||
|
soc = Consts.SOC_DSP
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (socList.contains(Consts.SOC_ADRENO_GPU) && Build.HARDWARE.equals(
|
||||||
|
"qcom",
|
||||||
|
ignoreCase = true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
soc = Consts.SOC_ADRENO_GPU
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (socList.contains(Consts.SOC_NPU) && Build.HARDWARE.contains("kirin980")) {
|
||||||
|
soc = "npu200"
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (socList.contains(Consts.SOC_NPU_VINCI)
|
||||||
|
&& (Build.HARDWARE.contains("kirin810") || Build.HARDWARE.contains("kirin820")
|
||||||
|
|| Build.HARDWARE.contains("kirin990") || Build.HARDWARE.contains("kirin985"))
|
||||||
|
) {
|
||||||
|
soc = Consts.SOC_NPU_VINCI
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (socList.contains(Consts.SOC_ARM_GPU)) {
|
||||||
|
try {
|
||||||
|
if (InferManager.isSupportOpencl()) {
|
||||||
|
soc = Consts.SOC_ARM_GPU
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} catch (e: CallException) {
|
||||||
|
Toast.makeText(
|
||||||
|
mContext, e.errorCode.toString() + ", " + e.message,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (socList.contains(Consts.SOC_ARM)) {
|
||||||
|
soc = Consts.SOC_ARM
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init(context: Context) {
|
||||||
|
mContext = context
|
||||||
|
if (initConfigFromDemoConfig()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (initConfigFromDemoConf()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 从infer/读配置 */
|
||||||
|
var confJson = FileUtil.readAssetsFileUTF8StringIfExists(
|
||||||
|
mContext!!.applicationContext.assets,
|
||||||
|
Consts.ASSETS_DIR_ARM + "/conf.json"
|
||||||
|
)
|
||||||
|
if (!TextUtils.isEmpty(confJson)) {
|
||||||
|
try {
|
||||||
|
val confObj = JSONObject(confJson)
|
||||||
|
modelName = confObj.optString("modelName", "")
|
||||||
|
val str = confObj.optString("soc", Consts.SOC_ARM)
|
||||||
|
val socs = str.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
socList.addAll(listOf(*socs))
|
||||||
|
modelType = confObj.getInt("modelType")
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
confJson = FileUtil.readAssetsFileUTF8StringIfExists(
|
||||||
|
mContext!!.applicationContext.assets,
|
||||||
|
Consts.ASSETS_DIR_ARM + "/infer_cfg.json"
|
||||||
|
)
|
||||||
|
try {
|
||||||
|
val confObj = JSONObject(confJson)
|
||||||
|
socList.add(Consts.SOC_ARM)
|
||||||
|
modelType = confObj.getJSONObject("model_info").getInt("model_kind")
|
||||||
|
} catch (e: JSONException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MainScope().launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
Log.e("jingo", "OCRManager 线程名称 ${Thread.currentThread().name}")
|
||||||
|
/* 1. 准备配置类,初始化Manager类。可以在onCreate或onResume中触发,请在非UI线程里调用 */
|
||||||
|
val config = InferConfig(context.assets, "infer")
|
||||||
|
mOcrManager = InferManager(mContext, config, SERIAL_NUM)
|
||||||
|
// cancel()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("jingo", "OCRManager 线程名称 ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val instance: OCRManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
|
||||||
|
OCRManager()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请替换为您的序列号
|
||||||
|
private const val SERIAL_NUM = "XXXX-XXXX-XXXX-XXXX"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,209 @@
|
|||||||
|
package com.navinfo.ocr.model;
|
||||||
|
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BasePolygonResultModel extends BaseResultModel implements Parcelable {
|
||||||
|
private int colorId;
|
||||||
|
private boolean isRect;
|
||||||
|
private boolean isTextOverlay;
|
||||||
|
|
||||||
|
private boolean isHasGroupColor = false;
|
||||||
|
private boolean isDrawPoints = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 姿态一个点会有多个pair
|
||||||
|
*/
|
||||||
|
private boolean multiplePairs = false;
|
||||||
|
|
||||||
|
protected BasePolygonResultModel(Parcel in) {
|
||||||
|
super(in);
|
||||||
|
colorId = in.readInt();
|
||||||
|
isRect = in.readByte() != 0;
|
||||||
|
isTextOverlay = in.readByte() != 0;
|
||||||
|
isHasGroupColor = in.readByte() != 0;
|
||||||
|
isDrawPoints = in.readByte() != 0;
|
||||||
|
multiplePairs = in.readByte() != 0;
|
||||||
|
in.readByteArray(mask);
|
||||||
|
semanticMask = in.readByte() != 0;
|
||||||
|
rect = in.readParcelable(Rect.class.getClassLoader());
|
||||||
|
bounds = in.createTypedArrayList(Point.CREATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<BasePolygonResultModel> CREATOR = new Creator<BasePolygonResultModel>() {
|
||||||
|
@Override
|
||||||
|
public BasePolygonResultModel createFromParcel(Parcel in) {
|
||||||
|
return new BasePolygonResultModel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BasePolygonResultModel[] newArray(int size) {
|
||||||
|
return new BasePolygonResultModel[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public boolean isTextOverlay() {
|
||||||
|
return isTextOverlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTextOverlay(boolean textOverlay) {
|
||||||
|
isTextOverlay = textOverlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColorId() {
|
||||||
|
return colorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorId(int colorId) {
|
||||||
|
this.colorId = colorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] mask = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是语义分割mask
|
||||||
|
*/
|
||||||
|
private boolean semanticMask;
|
||||||
|
|
||||||
|
private Rect rect;
|
||||||
|
|
||||||
|
BasePolygonResultModel() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
BasePolygonResultModel(int index, String name, float confidence, Rect bounds) {
|
||||||
|
super(index, name, confidence);
|
||||||
|
parseFromRect(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
BasePolygonResultModel(int index, String name, float confidence, List<Point> bounds) {
|
||||||
|
super(index, name, confidence);
|
||||||
|
this.bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect getRect() {
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect getRect(float ratio, Point origin) {
|
||||||
|
return new Rect((int) (origin.x + rect.left * ratio),
|
||||||
|
(int) (origin.y + rect.top * ratio),
|
||||||
|
(int) (origin.x + rect.right * ratio),
|
||||||
|
(int) (origin.y + rect.bottom * ratio));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseFromRect(Rect rect) {
|
||||||
|
Point ptTL = new Point(rect.left, rect.top);
|
||||||
|
Point ptTR = new Point(rect.right, rect.top);
|
||||||
|
Point ptRB = new Point(rect.right, rect.bottom);
|
||||||
|
Point ptLB = new Point(rect.left, rect.bottom);
|
||||||
|
this.bounds = new ArrayList<>();
|
||||||
|
this.bounds.add(ptTL);
|
||||||
|
this.bounds.add(ptTR);
|
||||||
|
this.bounds.add(ptRB);
|
||||||
|
this.bounds.add(ptLB);
|
||||||
|
this.rect = rect;
|
||||||
|
isRect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRect() {
|
||||||
|
return isRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRect(boolean rect) {
|
||||||
|
isRect = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getMask() {
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMask(byte[] mask) {
|
||||||
|
this.mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSemanticMask(boolean semanticMask) {
|
||||||
|
this.semanticMask = semanticMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSemanticMask() {
|
||||||
|
return semanticMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Point> bounds;
|
||||||
|
|
||||||
|
public List<Point> getBounds() {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Point> getBounds(float ratio, Point origin) {
|
||||||
|
List<Point> pointList = new ArrayList<>();
|
||||||
|
for (Point pt : bounds) {
|
||||||
|
int nx = (int) (origin.x + pt.x * ratio);
|
||||||
|
int ny = (int) (origin.y + pt.y * ratio);
|
||||||
|
pointList.add(new Point(nx, ny));
|
||||||
|
}
|
||||||
|
return pointList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBounds(List<Point> bounds) {
|
||||||
|
this.bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBounds(Rect bounds) {
|
||||||
|
parseFromRect(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasMask() {
|
||||||
|
return (mask != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasGroupColor() {
|
||||||
|
return isHasGroupColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasGroupColor(boolean hasGroupColor) {
|
||||||
|
isHasGroupColor = hasGroupColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDrawPoints() {
|
||||||
|
return isDrawPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDrawPoints(boolean drawPoints) {
|
||||||
|
isDrawPoints = drawPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMultiplePairs(boolean multiplePairs) {
|
||||||
|
this.multiplePairs = multiplePairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMultiplePairs() {
|
||||||
|
return multiplePairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
super.writeToParcel(dest,flags);
|
||||||
|
dest.writeInt(colorId);
|
||||||
|
dest.writeByte((byte) (isRect ? 1 : 0));
|
||||||
|
dest.writeByte((byte) (isTextOverlay ? 1 : 0));
|
||||||
|
dest.writeByte((byte) (isHasGroupColor ? 1 : 0));
|
||||||
|
dest.writeByte((byte) (isDrawPoints ? 1 : 0));
|
||||||
|
dest.writeByte((byte) (multiplePairs ? 1 : 0));
|
||||||
|
dest.writeByteArray(mask);
|
||||||
|
dest.writeByte((byte) (semanticMask ? 1 : 0));
|
||||||
|
dest.writeParcelable(rect, flags);
|
||||||
|
dest.writeTypedList(bounds);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package com.navinfo.ocr.model;
|
||||||
|
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ruanshimin on 2018/5/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BaseRectBoundResultModel extends BaseResultModel implements Parcelable {
|
||||||
|
|
||||||
|
private int colorId;
|
||||||
|
|
||||||
|
protected BaseRectBoundResultModel(Parcel in) {
|
||||||
|
super(in);
|
||||||
|
colorId = in.readInt();
|
||||||
|
in.readByteArray(mask);
|
||||||
|
bounds = in.readParcelable(Rect.class.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<BaseRectBoundResultModel> CREATOR = new Creator<BaseRectBoundResultModel>() {
|
||||||
|
@Override
|
||||||
|
public BaseRectBoundResultModel createFromParcel(Parcel in) {
|
||||||
|
return new BaseRectBoundResultModel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseRectBoundResultModel[] newArray(int size) {
|
||||||
|
return new BaseRectBoundResultModel[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public int getColorId() {
|
||||||
|
return colorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColorId(int colorId) {
|
||||||
|
this.colorId = colorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] mask = {};
|
||||||
|
|
||||||
|
BaseRectBoundResultModel() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseRectBoundResultModel(int index, String name, float confidence, Rect bounds) {
|
||||||
|
super(index, name, confidence);
|
||||||
|
this.bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getMask() {
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMask(byte[] mask) {
|
||||||
|
this.mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rect bounds;
|
||||||
|
|
||||||
|
public Rect getBounds() {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect getBounds(float ratio, Point origin) {
|
||||||
|
return new Rect((int) (origin.x + bounds.left * ratio),
|
||||||
|
(int) (origin.y + bounds.top * ratio),
|
||||||
|
(int) (origin.x + bounds.right * ratio),
|
||||||
|
(int) (origin.y + bounds.bottom * ratio));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBounds(Rect bounds) {
|
||||||
|
this.bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasMask() {
|
||||||
|
return (mask != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
super.writeToParcel(dest, flags);
|
||||||
|
dest.writeInt(colorId);
|
||||||
|
dest.writeByteArray(mask);
|
||||||
|
dest.writeParcelable(bounds, flags);
|
||||||
|
}
|
||||||
|
}
|
80
ocr/src/main/java/com/navinfo/ocr/model/BaseResultModel.java
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package com.navinfo.ocr.model;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ruanshimin on 2018/5/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class BaseResultModel implements Parcelable {
|
||||||
|
private int index = 0;
|
||||||
|
private String name = "";
|
||||||
|
private float confidence = 0;
|
||||||
|
|
||||||
|
protected BaseResultModel() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BaseResultModel(int index, String name, float confidence) {
|
||||||
|
this.index = index;
|
||||||
|
this.name = name;
|
||||||
|
this.confidence = confidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BaseResultModel(Parcel in) {
|
||||||
|
index = in.readInt();
|
||||||
|
name = in.readString();
|
||||||
|
confidence = in.readFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<BaseResultModel> CREATOR = new Creator<BaseResultModel>() {
|
||||||
|
@Override
|
||||||
|
public BaseResultModel createFromParcel(Parcel in) {
|
||||||
|
return new BaseResultModel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseResultModel[] newArray(int size) {
|
||||||
|
return new BaseResultModel[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public float getConfidence() {
|
||||||
|
return confidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfidence(float confidence) {
|
||||||
|
this.confidence = confidence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIndex(int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeInt(index);
|
||||||
|
dest.writeString(name);
|
||||||
|
dest.writeFloat(confidence);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.navinfo.ocr.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ruanshimin on 2018/5/13.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ClassifyResultModel extends BaseResultModel {
|
||||||
|
|
||||||
|
|
||||||
|
public ClassifyResultModel() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassifyResultModel(int index, String name, float confidence) {
|
||||||
|
|
||||||
|
super(index, name, confidence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.navinfo.ocr.model;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ruanshimin on 2018/5/13.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DetectResultModel extends BasePolygonResultModel {
|
||||||
|
public DetectResultModel() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DetectResultModel(int index, String name, float confidence, Rect bounds) {
|
||||||
|
super(index, name, confidence, bounds);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.navinfo.ocr.model;
|
||||||
|
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class OcrViewResultModel extends BasePolygonResultModel{
|
||||||
|
public OcrViewResultModel() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OcrViewResultModel(int index, String name, float confidence, List<Point> bounds) {
|
||||||
|
super(index, name, confidence, bounds);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.navinfo.ocr.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class PoseViewResultModel extends BasePolygonResultModel {
|
||||||
|
public PoseViewResultModel() {
|
||||||
|
super();
|
||||||
|
setRect(false);
|
||||||
|
setTextOverlay(false);
|
||||||
|
setDrawPoints(true);
|
||||||
|
setMultiplePairs(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.navinfo.ocr.model;
|
||||||
|
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by ruanshimin on 2018/5/13.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class SegmentResultModel extends BasePolygonResultModel {
|
||||||
|
|
||||||
|
public SegmentResultModel() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SegmentResultModel(int index, String name, float confidence, List<Point> bounds, byte[] mask) {
|
||||||
|
super(index, name, confidence, bounds);
|
||||||
|
this.setMask(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SegmentResultModel(int index, String name, float confidence, List<Point> bounds) {
|
||||||
|
super(index, name, confidence, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
30
ocr/src/main/res/drawable-v24/ic_launcher_foreground.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="85.84757"
|
||||||
|
android:endY="92.4963"
|
||||||
|
android:startX="42.9492"
|
||||||
|
android:startY="49.59793"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
</vector>
|
170
ocr/src/main/res/drawable/ic_launcher_background.xml
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path
|
||||||
|
android:fillColor="#3DDC84"
|
||||||
|
android:pathData="M0,0h108v108h-108z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M9,0L9,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,0L19,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,0L29,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,0L39,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,0L49,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,0L59,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,0L69,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,0L79,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M89,0L89,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M99,0L99,108"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,9L108,9"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,19L108,19"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,29L108,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,39L108,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,49L108,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,59L108,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,69L108,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,79L108,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,89L108,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M0,99L108,99"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,29L89,29"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,39L89,39"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,49L89,49"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,59L89,59"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,69L89,69"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M19,79L89,79"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M29,19L29,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M39,19L39,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M49,19L49,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M59,19L59,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M69,19L69,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:pathData="M79,19L79,89"
|
||||||
|
android:strokeWidth="0.8"
|
||||||
|
android:strokeColor="#33FFFFFF" />
|
||||||
|
</vector>
|
5
ocr/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
5
ocr/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
6
ocr/src/main/res/mipmap-anydpi-v33/ic_launcher.xml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@drawable/ic_launcher_background" />
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||||
|
</adaptive-icon>
|
BIN
ocr/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
ocr/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
ocr/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 982 B |
BIN
ocr/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
ocr/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
ocr/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
ocr/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
ocr/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
ocr/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
ocr/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 7.6 KiB |
16
ocr/src/main/res/values-night/themes.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.NavinfoCollect" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/purple_200</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/black</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
10
ocr/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="purple_200">#FFBB86FC</color>
|
||||||
|
<color name="purple_500">#FF6200EE</color>
|
||||||
|
<color name="purple_700">#FF3700B3</color>
|
||||||
|
<color name="teal_200">#FF03DAC5</color>
|
||||||
|
<color name="teal_700">#FF018786</color>
|
||||||
|
<color name="black">#FF000000</color>
|
||||||
|
<color name="white">#FFFFFFFF</color>
|
||||||
|
</resources>
|
3
ocr/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<resources>
|
||||||
|
<string name="app_name">ocr</string>
|
||||||
|
</resources>
|
16
ocr/src/main/res/values/themes.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.NavinfoCollect" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">@color/purple_500</item>
|
||||||
|
<item name="colorPrimaryVariant">@color/purple_700</item>
|
||||||
|
<item name="colorOnPrimary">@color/white</item>
|
||||||
|
<!-- Secondary brand color. -->
|
||||||
|
<item name="colorSecondary">@color/teal_200</item>
|
||||||
|
<item name="colorSecondaryVariant">@color/teal_700</item>
|
||||||
|
<item name="colorOnSecondary">@color/black</item>
|
||||||
|
<!-- Status bar color. -->
|
||||||
|
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
17
ocr/src/test/java/com/navinfo/ocr/ExampleUnitTest.kt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package com.navinfo.ocr
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
fun addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2)
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
include ':app', ':xrecyclerview'
|
include ':app', ':xrecyclerview', ":ocr"
|