下载SDK mode导入
implementation project(path: ':opencvsdk')
//opencvsdk 的gradle
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Notes about integration OpenCV into existed Android Studio application project are below (application 'app' module should exist).
//
// This file is located in <OpenCV-android-sdk>/sdk directory (near 'etc', 'java', 'native' subdirectories)
//
// Add module into Android Studio application project:
//
// - Android Studio way:
// (will copy almost all OpenCV Android SDK into your project, ~200Mb)
//
// Import module: Menu -> "File" -> "New" -> "Module" -> "Import Gradle project":
// Source directory: select this "sdk" directory
// Module name: ":opencv"
//
// - or attach library module from OpenCV Android SDK
// (without copying into application project directory, allow to share the same module between projects)
//
// Edit "settings.gradle" and add these lines:
//
// def opencvsdk='<path_to_opencv_android_sdk_rootdir>'
// // You can put declaration above into gradle.properties file instead (including file in HOME directory),
// // but without 'def' and apostrophe symbols ('): opencvsdk=<path_to_opencv_android_sdk_rootdir>
// include ':opencv'
// project(':opencv').projectDir = new File(opencvsdk + '/sdk')
//
//
//
// Add dependency into application module:
//
// - Android Studio way:
// "Open Module Settings" (F4) -> "Dependencies" tab
//
// - or add "project(':opencv')" dependency into app/build.gradle:
//
// dependencies {
// implementation fileTree(dir: 'libs', include: ['*.jar'])
// ...
// implementation project(':opencv')
// }
//
//
//
// Load OpenCV native library before using:
//
// - avoid using of "OpenCVLoader.initAsync()" approach - it is deprecated
// It may load library with different version (from OpenCV Android Manager, which is installed separatelly on device)
//
// - use "System.loadLibrary("opencv_java4")" or "OpenCVLoader.initDebug()"
// TODO: Add accurate API to load OpenCV native library
//
//
//
// Native C++ support (necessary to use OpenCV in native code of application only):
//
// - Use find_package() in app/CMakeLists.txt:
//
// find_package(OpenCV 3.4 REQUIRED java)
// ...
// target_link_libraries(native-lib ${OpenCV_LIBRARIES})
//
// - Add "OpenCV_DIR" and enable C++ exceptions/RTTI support via app/build.gradle
// Documentation about CMake options: https://developer.android.com/ndk/guides/cmake.html
//
// defaultConfig {
// ...
// externalNativeBuild {
// cmake {
// cppFlags "-std=c++11 -frtti -fexceptions"
// arguments "-DOpenCV_DIR=" + opencvsdk + "/sdk/native/jni" // , "-DANDROID_ARM_NEON=TRUE"
// }
// }
// }
//
// - (optional) Limit/filter ABIs to build ('android' scope of 'app/build.gradle'):
// Useful information: https://developer.android.com/studio/build/gradle-tips.html (Configure separate APKs per ABI)
//
// splits {
// abi {
// enable true
// universalApk false
// reset()
// include 'armeabi-v7a' // , 'x86', 'x86_64', 'arm64-v8a'
// }
// }
//
apply plugin: 'com.android.library'
def openCVersionName = "4.3.0"
def openCVersionCode = ((4 * 100 + 3) * 100 + 0) * 10 + 0
println "OpenCV: " +openCVersionName + " " + project.buildscript.sourceFile
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 21
targetSdkVersion 26
versionCode openCVersionCode
versionName openCVersionName
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_shared"
targets "opencv_jni_shared"
}
}
}
buildTypes {
debug {
packagingOptions {
doNotStrip '**/*.so' // controlled by OpenCV CMake scripts
}
}
release {
packagingOptions {
doNotStrip '**/*.so' // controlled by OpenCV CMake scripts
}
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_6
targetCompatibility JavaVersion.VERSION_1_6
}
sourceSets {
main {
jniLibs.srcDirs = ['native/libs']
java.srcDirs = ['java/src']
aidl.srcDirs = ['java/src']
res.srcDirs = ['java/res']
manifest.srcFile 'java/AndroidManifest.xml'
}
}
externalNativeBuild {
cmake {
path (project.projectDir.toString() + '/libcxx_helper/CMakeLists.txt')
}
}
}
dependencies {
}
//使用
//判断是否加载成功 if (!OpenCVLoader.initDebug()) { Log.d("TAG", "Internal OpenCV library not found. Using OpenCV Manager for initialization"); // OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, null); } else { Log.d("TAG", "OpenCV library found inside package. Using it!"); }
使用openvc比较图片,可以使用相机拍照
public class HistUtils {
/**
* 比较来个矩阵的相似度
*
* @param mBitmap1
* @param mBitmap2
* @return
*/
public static double comPareHist(Bitmap mBitmap1, Bitmap mBitmap2) {
mBitmap2 = imageScale(mBitmap1,mBitmap2);
Mat mat1 = new Mat();
Mat mat2 = new Mat();
Utils.bitmapToMat(mBitmap1, mat1);
Utils.bitmapToMat(mBitmap2, mat2);
return comPareHist(mat1, mat2);
}
/**
* 调整图片大小
*
* @return
*/
public static Bitmap imageScale(Bitmap bitmap1,Bitmap bitmap2) {
int dst_w = bitmap1.getWidth();
int dst_h = bitmap1.getHeight();
int src_w = bitmap2.getWidth();
int src_h = bitmap2.getHeight();
float scale_w = ((float) dst_w) / src_w;
float scale_h = ((float) dst_h) / src_h;
Matrix matrix = new Matrix();
matrix.postScale(scale_w, scale_h);
Bitmap dstbmp = Bitmap.createBitmap(bitmap2, 0, 0, src_w, src_h, matrix,
true);
return dstbmp;
}
public static Mat yuv420(Image image) {
// yuv420图片有三个通道,按顺序下来分别对应YUV
// 转换需要把三个通道的数据按顺序合并在一个数组里,
// 即全部Y,随后全部U,再随后全部是V,
// 再由此数组生成Yuv420的Mat,
// 之后可以利用opencv将其转为其他格式
Image.Plane[] plans = image.getPlanes();
ByteBuffer y = plans[0].getBuffer();
ByteBuffer u = plans[1].getBuffer();
ByteBuffer v = plans[2].getBuffer();
// 此处需要把postition移到0才能读取
y.position(0);
u.position(0);
v.position(0);
int yl = y.remaining();
// yuv420即4个Y对应1个U和一个V,即4:1:1的关系,长度刚好是Y的1.5倍
ByteBuffer data = ByteBuffer.allocateDirect(yl * 3 / 2);
// y通道直接全部插入
data.put(y);
copy(data, u, yl);
copy(data, v, yl);
// 生成Yuv420格式的Mat
int rows = image.getHeight();
int cols = image.getWidth();
return new Mat(rows * 3 / 2, cols, CvType.CV_8UC1, data);
}
// 复制uv通道数据
private static void copy(ByteBuffer data, ByteBuffer uv, int yl) {
int l = uv.remaining();
int quarter = yl / 4;
int half = yl / 2;
if (l == quarter) {
// 魅族M8,长度刚好是y的四分之一,直接写入。
data.put(uv);
} else if (quarter < l && l <= half) {
// 华为荣耀,实际读取到的长度是y的(1 / 2 - 1)
for (int i = 0; i < l; i++) {
byte b = uv.get();
if (i % 2 == 0) {
data.put(b);
}
}
} else if (l > half) {
// 未发现此种情况,先预留着
for (int i = 0; i < l; i++) {
byte b = uv.get();
if (i % 4 == 0) {
data.put(b);
}
}
}
}
/**
* 比较来个矩阵的相似度
*
* @param mat1
* @param mat2
* @return
*/
public static double comPareHist(Mat mat1, Mat mat2) {
Mat srcMat = new Mat();
Mat desMat = new Mat();
Imgproc.cvtColor(mat1, srcMat, Imgproc.COLOR_BGR2GRAY);
Imgproc.cvtColor(mat2, desMat, Imgproc.COLOR_BGR2GRAY);
srcMat.convertTo(srcMat, CvType.CV_32F);
desMat.convertTo(desMat, CvType.CV_32F);
double target = Imgproc.compareHist(srcMat, desMat,
Imgproc.CV_COMP_CORREL);
return target;
}
}
使用相机拍照部分代码
private Bitmap bmp1, bmp2;
private TextView textView;
private Camera mCamera = null;
mSurfaceView = findViewById(R.id.surface_view);
SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mSurfaceHolder.addCallback(new NewSurfaceHolder());
class NewSurfaceHolder implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
L.e("surfaceCreated");
try {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
int numberOfCameras = Camera.getNumberOfCameras();
if (numberOfCameras > 0) {
mCamera = Camera.open(0);
mCameraIsOpening = true;
mCamera.setPreviewDisplay(holder);
// mCamera.startPreview();
}
} catch (Exception e) {
e.printStackTrace();
writeLog(e.toString());
// T.showShort(context, e.toString());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
L.e("surfaceChanged");
new Handler().postDelayed(
() -> {
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters(); // 获取各项参数
parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式
parameters.setJpegQuality(40); // 设置照片质量
// 以下不设置在某些机型上报错
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
writeLog("支持的宽高:"+new Gson().toJson(sizeList));
int w0 = sizeList.get(0).width;
int h0 = sizeList.get(0).height;
for(int i =0; i < sizeList.size();i++){
if(w0>sizeList.get(i).width){
if(sizeList.get(i).width>=640){
w0 = sizeList.get(i).width;
h0 = sizeList.get(i).height;
}
}
}
parameters.setPreviewSize(w0, h0);
writeLog("预览宽高 :"+w0 + " * " + h0);
List<Camera.Size> picSizeList = parameters.getSupportedPictureSizes();
writeLog("支持的图片宽高:"+new Gson().toJson(picSizeList));
int picW0 = picSizeList.get(0).width;
int picH0 = picSizeList.get(0).height;
for(int i =0; i < picSizeList.size();i++){
if(picW0>picSizeList.get(i).width){
if(picSizeList.get(i).width>=640){
picW0 = picSizeList.get(i).width;
picH0 = picSizeList.get(i).height;
}
}
}
parameters.setPictureSize(picW0, picH0);
writeLog("预览图片宽高 :"+picW0 + " * " + picH0);
mCamera.setParameters(parameters);
mCamera.startPreview();
mCameraIsOpening = false;
}
}
, 5000);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
L.e("surfaceDestroyed");
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
}
//拍照
private void getPicture() {
if (mCamera != null && !mCameraIsOpening) {
try {
mCamera.takePicture(null, null, (data, camera) -> {
Bitmap source = BitmapFactory.decodeByteArray(data, 0, data.length);
if (bmp1 == null) {
bmp1 = source;
} else {
bmp2 = source;
hist();
}
// mCamera.startPreview();
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
@SuppressLint({"DefaultLocale", "SetTextI18n"})
private void hist() {
L.e("hist");
new Thread(() -> {
if (bmp1 != null & bmp2 != null) {
final double target = HistUtils.comPareHist(bmp1, bmp2);
L.e(target + "");
//975 980 990
if (target < Datas.threshold) {
}
activity.runOnUiThread(() -> {
textView.setText(String.format("%.6f", target) + "\n");
cameraPicIndex++;
if (cameraPicIndex > 3) {
bmp1 = bmp2;
cameraPicIndex = 0;
}
});
}
}).start();
}