我正在使用openCV处理相机,并尝试首先找到轮廓然后在图像上绘制轮廓来扫描文档。但是当我尝试从jni函数返回float[]
时,我收到此错误。如果我的jni函数的返回类型无效,我的应用程序正常工作
日志条目:
D/Scanner: OpenCV library found inside package. Using it!
I/Scanner: onManagerConnected
D/CameraBridge: call checkCurrentState
D/ActivityThreadInjector: clearCachedDrawables.
D/Fabric: Using AdvertisingInfo from Service Provider
D/CameraBridge: call surfaceChanged event
D/CameraBridge: call checkCurrentState
D/CameraBridge: call processExitState: 0
D/CameraBridge: call processEnterState: 1
D/CameraBridge: call onEnterStartedState
D/JavaCameraView: Connecting to camera
D/JavaCameraView: Initialize java camera
D/JavaCameraView: Trying to open camera with old open()
D/JavaCameraView: getSupportedPreviewSizes()
D/JavaCameraView: Set preview size to 1920x1080
D/JavaCameraView: startPreview
I/art: Background partial concurrent mark sweep GC freed 42524(4MB) AllocSpace objects, 19(364KB) LOS objects, 40% free, 29MB/49MB, paused 5.552ms total 28.751ms
D/JavaCameraView: Starting processing thread
A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 7104 (Thread-8360)
我在某处读到大多数设备在硬件加速方面都不能很好地工作,所以我在清单文件中禁用它。即使在禁用硬件加速后,我也会遇到同样的错误。
清单文件
<activity android:name=".MainActivity"
android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation"
android:hardwareAccelerated="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
onCameraFrame方法(MainActivity.java)
@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
rgba = inputFrame.rgba();
// Finding contours that represents the piece of paper being scanned
float[] points = ScannerNative.drawContours(rgba.getNativeObjAddr());
if(points.length == 8){
Log.d(TAG,"" + points[0] + "x" + points[4]);
Log.d(TAG,"" + points[1] + "x" + points[5]);
Log.d(TAG,"" + points[2] + "x" + points[6]);
Log.d(TAG,"" + points[3] + "x" + points[7]);
}
return rgba;
}
ScannerNative.java
public class ScannerNative {
public native static float[] drawContours(long matAddrRgba);
}
Jni功能
JNIEXPORT jfloatArray JNICALL Java_aac_scanner_ScannerNative_drawContours(JNIEnv *env, jclass thiz, jlong addrRgba){
Mat& rgba = *(Mat*) addrRgba;
Mat gray = rgba.clone();
Mat canny = rgba.clone();
vector< vector<Point> > contours;
vector<Vec4i> hierarchy;
vector<Point> approx, approxCurves;
double area,maxArea=0.0,epsilon;
cvtColor(rgba, gray, CV_RGBA2GRAY);
GaussianBlur(gray, gray, Size(5,5), 0, 0);
Canny(gray,canny,75,200);
findContours( canny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
canny.release();
gray.release();
for(int i=0;i<contours.size();i++){
area = contourArea(contours[i]);
epsilon = arcLength(contours[i], true)*0.02;
approxPolyDP(contours[i], approxCurves, epsilon, true);
if(area > maxArea && approxCurves.size() == 4 && fabs(area) > 1000 && isContourConvex(Mat(approx))){
maxArea = area;
approx = approxCurves;
}
}
contours.erase(contours.begin(),contours.end());
contours.push_back(approx);
drawContours(rgba,contours,-1, Scalar(0,255,0), 2);
jfloatArray jArray = env->NewFloatArray(8);
if (jArray != NULL) {
jfloat *ptr = env->GetFloatArrayElements(jArray, NULL);
for (int i=0,j=i+4; j<8; i++,j++) {
ptr[i] = approx[i].x;
ptr[j] = approx[i].y;
}
env->ReleaseFloatArrayElements(jArray, ptr, NULL);
}
if(maxArea != 0.0) {
LOGD("returnig array of points");
return jArray;
}
else {
LOGD("returnig 0");
return 0;
}
}