Android opencv sdk ndk 接入方法
https://www.jianshu.com/p/6e16c0429044
opencv 常用api
1、截屏
package com.qxtool;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Environment;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
public class BMPUtils {
private Point Hµ;
static {//加载so库
// System.load("/data/local/tmp/libnative-opencv.so");
}
public boolean saveBitmap(Bitmap bitmap, File file) {
if (bitmap == null)
return false;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
public final Bitmap getRect(int oriention, Rect v7, int type) {
Bitmap v0;
if (Build.VERSION.SDK_INT >= 28) {
v0 = screenshot(v7, v7.width(), v7.height(), oriention);
} else {
if (oriention == 1 || oriention == 3) {
oriention = oriention == 1 ? 3 : 1;
}
μΡ(v7, oriention);
v0 = screenshot(v7, v7.height(), v7.width(), 0x80000000, 0x7FFFFFFF, false, oriention);
}
System.out.println("bmp:" + v0);
File file = new File(Environment.getExternalStorageDirectory(), "Log/default.jpg");
if (type == 2) {
file = new File(Environment.getExternalStorageDirectory(), "Log/weapon.jpg");
} else if (type == 3) {
file = new File(Environment.getExternalStorageDirectory(), "Log/accessories1.jpg");
}
if (!file.getParentFile().exists()) {
file.mkdirs();
}
if (("huawei".equalsIgnoreCase(Build.BRAND)) && ((Build.MODEL.startsWith("LIO-AN")) || (Build.MODEL.startsWith("LIO-TN")) || (Build.MODEL.startsWith("LIO-AL")) || (Build.MODEL.startsWith("LIO-TL")))) {
this.Hµ = new Point((v7.width() - v0.getWidth()) / 2, (v7.height() - v0.getHeight()) / 2);
}
if (v0 != null)
saveBitmap(v0, file);
return v0;
}
public final Bitmap getBMP(Rect arg9, int oriention) {
if (Build.VERSION.SDK_INT >= 28) {
return screenshot(arg9, arg9.width(), arg9.height(), oriention);
}
int v0 = oriention;
if (v0 == 1 || v0 == 3) {
v0 = v0 == 1 ? 3 : 1;
}
μΡ(arg9, v0);
return screenshot(arg9, arg9.height(), arg9.width(), 0x80000000, 0x7FFFFFFF, false, v0);
}
public Bitmap screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer, boolean useIdentityTransform, int rotation) {
try {
Class<?> demo = Class.forName("android.view.SurfaceControl");
Method method = demo.getDeclaredMethod("screenshot", Rect.class, int.class, int.class, int.class, int.class, boolean.class, int.class);
// method.setAccessible(true);
return (Bitmap) method.invoke(null, sourceCrop, width, height, minLayer, maxLayer, useIdentityTransform, rotation);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
try {
Class<?> demo = Class.forName("android.view.SurfaceControl");
Method method = demo.getDeclaredMethod("screenshot", Rect.class, int.class, int.class, int.class);
// method.setAccessible(true);
return (Bitmap) method.invoke(null, sourceCrop, width, height, rotation);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void μΡ(Rect arg1, int arg2) {
if (arg2 == 1 || arg2 == 3) {
arg2 = arg1.top;
arg1.top = arg1.left;
arg1.left = arg2;
arg2 = arg1.right;
arg1.right = arg1.bottom;
arg1.bottom = arg2;
}
}
}
2、mat2bitmap bitmap2mat
void BitmapToMat2(JNIEnv *env, jobject &bitmap, Mat &mat, jboolean needUnPremultiplyAlpha) {
AndroidBitmapInfo info;
void *pixels = 0;
Mat &dst = mat;
try {
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565);
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
CV_Assert(pixels);
dst.create(info.height, info.width, CV_8UC4);
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
Mat tmp(info.height, info.width, CV_8UC4, pixels);
if (needUnPremultiplyAlpha) cvtColor(tmp, dst, COLOR_mRGBA2RGBA);
else tmp.copyTo(dst);
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
Mat tmp(info.height, info.width, CV_8UC2, pixels);
cvtColor(tmp, dst, COLOR_BGR5652RGBA);
}
AndroidBitmap_unlockPixels(env, bitmap);
return;
} catch (const cv::Exception &e) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass("org/opencv/core/CvException");
if (!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return;
} catch (...) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}");
return;
}
}
void BitmapToMat(JNIEnv *env, jobject &bitmap, Mat &mat) {
BitmapToMat2(env, bitmap, mat, false);
}
void MatToBitmap2
(JNIEnv *env, Mat &mat, jobject &bitmap, jboolean needPremultiplyAlpha) {
AndroidBitmapInfo info;
void *pixels = 0;
Mat &src = mat;
try {
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565);
CV_Assert(src.dims == 2 && info.height == (uint32_t) src.rows &&
info.width == (uint32_t) src.cols);
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4);
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
CV_Assert(pixels);
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
Mat tmp(info.height, info.width, CV_8UC4, pixels);
if (src.type() == CV_8UC1) {
cvtColor(src, tmp, COLOR_GRAY2RGBA);
} else if (src.type() == CV_8UC3) {
cvtColor(src, tmp, COLOR_RGB2RGBA);
} else if (src.type() == CV_8UC4) {
if (needPremultiplyAlpha)
cvtColor(src, tmp, COLOR_RGBA2mRGBA);
else
src.copyTo(tmp);
}
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
Mat tmp(info.height, info.width, CV_8UC2, pixels);
if (src.type() == CV_8UC1) {
cvtColor(src, tmp, COLOR_GRAY2BGR565);
} else if (src.type() == CV_8UC3) {
cvtColor(src, tmp, COLOR_RGB2BGR565);
} else if (src.type() == CV_8UC4) {
cvtColor(src, tmp, COLOR_RGBA2BGR565);
}
}
AndroidBitmap_unlockPixels(env, bitmap);
return;
} catch (const cv::Exception &e) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass("org/opencv/core/CvException");
if (!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return;
} catch (...) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
return;
}
}
void MatToBitmap(JNIEnv *env, Mat &mat, jobject &bitmap) {
MatToBitmap2(env, mat, bitmap, false);
}
选用Android sdk 环境,在/data/local/temp/ 启动会爆出AndroidBitmap_lockPixels的异常
3、灰度化,二值化,轮廓
cvtColor(temp, gray, COLOR_RGB2GRAY);
threshold(gray, gray, 55, 255, THRESH_BINARY);
// Canny(gray, gray, 45, 75);//轮廓
std::vector<std::vector<Point>> vContours;
findContours(gray, vContours, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
std::vector<Rect> rects;
4、感知hash 算法比较图片
经过3的处理
//差值感知算法
long dHash(Mat srcMat, bool isGray) {
Mat dstMat;
resize(srcMat, dstMat, Size(8, 8), 0, 0, INTER_CUBIC);
if (!isGray)
cvtColor(dstMat, dstMat, COLOR_BGR2GRAY);
long hash_str = 0;
//每行前一个像素大于后一个像素为1,相反为0,生成哈希
for (int i = 0; i < 8; i++) {
uchar *data1 = dstMat.ptr<uchar>(i);
for (int j = 0; j < 8; j++) {
if (data1[j] > data1[j + 1]) {
hash_str ++;
}
}
}
return hash_str;
}
//平均值hash
long aHash(Mat srcMat, bool isGray) {
Mat dstMat;
resize(srcMat, dstMat, Size(8, 8), 0, 0, INTER_CUBIC);
if (!isGray)
cvtColor(dstMat, dstMat, COLOR_BGR2GRAY);
int iAvg = 0;
int arr[64];
for (int i = 0; i < 8; i++) {
uchar *data1 = dstMat.ptr<uchar>(i);
int tmp = i * 8;
for (int j = 0; j < 8; j++) {
int tmp1 = tmp + j;
arr[tmp1] = data1[j] / 4 * 4;
iAvg += arr[tmp1];
}
}
iAvg /= 64;
int p = 1;
long value = 0;
for (int i = 0; i < 64; i++) {
p *= 2;
if (arr[i] >= iAvg) {
value += p;
}
}
return value;
}
网友评论