利用OPENCV为android开发畸变校正的JNI库方法
需要为项目提供一套畸变校正的算法,由于需要大量的矩阵运算,考虑到效率和适时性,使用JNI开发,希望把有关数组短阵的处理的变换全部放入C语言中处理。
主要用于android移动端,大致的数据来源一是从camera直接读取YUV数据,一种是从第三方接读取RGB数据,另一种是直接对BITMAP进行处理。
1.考虑到硬件设备接口,第三方软件接口,图像接口,OPENCV接口,希望能够开发出通用的算法库,一劳永逸的解决各种复杂的使用场景,因此数据要支持YUV,支持ARGB,支持MAT
2android对BITMAP有获取像素点的操作,也有通过象素点生成BITMAP的操作,而且有很多图像处理接口和第三方可以处理RGB矩阵,如
bm.getPixels(pixs,0,w,0,0,w,h); int[]pixs1=newint[w*h]; finalBitmapbm2=Bitmap.createBitmap(pixs1,w,h,Bitmap.Config.ARGB_8888);
因此设计如下接口,入口为ARGB的整型,输出也是整型
publicstaticnativebooleanRgbaUndistort(int[]argb,intwidth,intheight,int[]pixels);
3考虑到有些情况需要二维数组,
publicstaticnativebooleanRgbaUndistort2(int[][]rgb,intwidth,intheight,int[]pixels);
4考虑到OPENCV的MAT结构,由于MAT有matToBitmap可以直接转化为BITMAP,应用MAT提供
publicstaticnativebooleanRgbaUndistortMat(int[]argb,intwidth,intheight,longpArgbOutMatAddr);
5考虑到第三方使用MAT的情况,因此输入也可以支持MAT因此设计接口
publicstaticnativebooleanRgbMatUndistortMat(longpArgbMatAddr,intwidth,intheight,longpArgbOutMatAddr);
6考虑到摄像头输出YUV,提供YUV数据处理,一个输出RGB,一个输出MAT
publicstaticnativebooleanYuvNv21UndistortRgba(byte[]YuvNv21,intwidth,intheight,int[]pixels); publicstaticnativebooleanYuvNv21UndistortRgbaMat(byte[]YuvNv21,intwidth,intheight,longpMatAddr);
7考虑到可能有不需要畸变的场合,为YUV设计一个灰度,一个RGB接口
publicstaticnativebooleanYuvNv21ToGray(byte[]YuvNv21,intwidth,intheight,int[]pixels); publicstaticnativebooleanYuvNv21ToRGBA(byte[]YuvNv21,intwidth,intheight,int[]pixels);
8于是编写简单的JAVA头源生类
publicclassImageProc3{ static{ System.loadLibrary("ImgProc3"); } publicstaticnativebooleanYuvNv21ToGray(byte[]YuvNv21,intwidth,intheight,int[]pixels); publicstaticnativebooleanYuvNv21ToRGBA(byte[]YuvNv21,intwidth,intheight,int[]pixels); publicstaticnativebooleanRgbaUndistort(int[]argb,intwidth,intheight,int[]pixels); publicstaticnativebooleanRgbaUndistort2(int[][]rgb,intwidth,intheight,int[]pixels); publicstaticnativebooleanRgbaUndistortMat(int[]argb,intwidth,intheight,longpArgbOutMatAddr); publicstaticnativebooleanRgbMatUndistortMat(longpArgbMatAddr,intwidth,intheight,longpArgbOutMatAddr); publicstaticnativebooleanYuvNv21UndistortRgba(byte[]YuvNv21,intwidth,intheight,int[]pixels); publicstaticnativebooleanYuvNv21UndistortRgbaMat(byte[]YuvNv21,intwidth,intheight,longpMatAddr); }
进入BIN目录的classes文件夹使用java-classpath.-jni生成C头文件
根据头文件编写实现的C代码
#include#include #include #include #include #include usingnamespacestd; usingnamespacecv; #defineTAG"CameraXXXXX"//锟斤拷锟斤拷锟斤拷远锟斤拷锟斤拷LOG锟侥憋拷识 #defineLOGD(...)__android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)//锟斤拷锟斤拷LOGD锟斤拷锟斤拷 #ifdef__cplusplus extern"C"{ #endif /* *Class:ImgProc_ImageProc3 *Method:YuvNv21ToGray *Signature:([BII[I)Z */ JNIEXPORTjbooleanJNICALLJava_ImgProc_ImageProc3_YuvNv21ToGray (JNIEnv*jenv,jclassjclassz,jbyteArrayYuvNv21,jintwidth,jintheight,jintArraypixels){ jbyte*pNV21FrameData=jenv->GetByteArrayElements(YuvNv21,0); jint*poutPixels=jenv->GetIntArrayElements(pixels,0); MatmNV(height,width,CV_8UC1,(unsignedchar*)pNV21FrameData); MatmBgra(height,width,CV_8UC4,(unsignedchar*)poutPixels); cvtColor(mNV,mBgra,CV_YUV420sp2RGBA); jenv->ReleaseByteArrayElements(YuvNv21,pNV21FrameData,0); jenv->ReleaseIntArrayElements(pixels,poutPixels,0); returntrue; } /* *Class:ImgProc_ImageProc3 *Method:YuvNv21ToRGBA *Signature:([BII[I)Z */ JNIEXPORTjbooleanJNICALLJava_ImgProc_ImageProc3_YuvNv21ToRGBA (JNIEnv*jenv,jclassjclassz,jbyteArrayYuvNv21,jintwidth,jintheight,jintArraypixels){ jbyte*pBuf=(jbyte*)jenv->GetByteArrayElements(YuvNv21,0); jint*poutPixels=jenv->GetIntArrayElements(pixels,0); Matimage(height+height/2,width,CV_8UC1,(unsignedchar*)pBuf); Matrgba(height,width,CV_8UC4,(unsignedchar*)poutPixels); Mattmp(height,width,CV_8UC4); cvtColor(image,tmp,CV_YUV420sp2RGBA); vector channels; split(tmp,channels); Matr=channels.at(0); Matg=channels.at(1); Matb=channels.at(2); Mata=channels.at(3); vector mbgr(4); mbgr[0]=b; mbgr[1]=g; mbgr[2]=r; mbgr[3]=a; merge(mbgr,rgba); jenv->ReleaseByteArrayElements(YuvNv21,pBuf,0); jenv->ReleaseIntArrayElements(pixels,poutPixels,0); returntrue; } /* *Class:ImgProc_ImageProc3 *Method:RgbaUndistort *Signature:([III[I)Z */ JNIEXPORTjbooleanJNICALLJava_ImgProc_ImageProc3_RgbaUndistort (JNIEnv*jenv,jclassjclassz,jintArrayargb,jintwidth,jintheight,jintArraypixels){ jint*poutPixels=jenv->GetIntArrayElements(pixels,0); jint*pinPixels=jenv->GetIntArrayElements(argb,0); Matout(height,width,CV_8UC4,(unsignedchar*)poutPixels); Matin(height,width,CV_8UC4,(unsignedchar*)pinPixels); doublecam[]={width,0,width/2,0,height,height/2,0,0,1}; doubledistort[]={0.1,0.35,0.0,0.0,0.01}; MatcamMat=Mat(3,3,CV_64FC1,cam); MatdisMat=Mat(5,1,CV_64FC1,distort); undistort(in,out,camMat,disMat); jenv->ReleaseIntArrayElements(argb,pinPixels,0); jenv->ReleaseIntArrayElements(pixels,poutPixels,0); returntrue; } /* *Class:ImgProc_ImageProc3 *Method:RgbaUndistort2 *Signature:([[III[I)Z */ JNIEXPORTjbooleanJNICALLJava_ImgProc_ImageProc3_RgbaUndistort2(JNIEnv*jenv, jclassjclassz,jobjectArrayargb,jintwidth,jintheight, jintArraypixels){ jinti,j; introw=jenv->GetArrayLength(argb); jintArraymyarray=(jintArray)(jenv->GetObjectArrayElement(argb,0)); intcol=jenv->GetArrayLength(myarray); jintjniData[row][col]; LOGD("jiaXXX%s","Java_ImgProc_ImageProc_convertRGB3"); for(i=0;i GetObjectArrayElement(argb,i)); jint*coldata=jenv->GetIntArrayElements(myarray,0); for(j=0;j
ReleaseIntArrayElements(myarray,coldata,0); } Matimg=Mat(row,col,CV_8UC4,jniData); LOGD("jiaXXX%x",img.at (1,1)); doublecam[]={width,0,width/2,0,height,height/2,0,0,1}; doubledistort[]={0.1,0.35,0.0,0.0,0.01}; MatcamMat=Mat(3,3,CV_64FC1,cam); MatdisMat=Mat(5,1,CV_64FC1,distort); jint*poutPixels=jenv->GetIntArrayElements(pixels,0); Matout(height,width,CV_8UC4,(unsignedchar*)poutPixels); undistort(img,out,camMat,disMat); jenv->ReleaseIntArrayElements(pixels,poutPixels,0); returntrue; } /* *Class:ImgProc_ImageProc3 *Method:RgbaUndistortMat *Signature:([IIIJ)Z */ JNIEXPORTjbooleanJNICALLJava_ImgProc_ImageProc3_RgbaUndistortMat (JNIEnv*jenv,jclassjclassz,jintArrayargb,jintwidth,jintheight,jlongpArgbOutMatAddr){ //jint*poutPixels=jenv->GetIntArrayElements(pixels,0); jint*pinPixels=jenv->GetIntArrayElements(argb,0); //Matout(height,width,CV_8UC4,(unsignedchar*)poutPixels); Matin(height,width,CV_8UC4,(unsignedchar*)pinPixels); Matout=*((Mat*)pArgbOutMatAddr); doublecam[]={width,0,width/2,0,height,height/2,0,0,1}; doubledistort[]={0.1,0.35,0.0,0.0,0.01}; MatcamMat=Mat(3,3,CV_64FC1,cam); MatdisMat=Mat(5,1,CV_64FC1,distort); undistort(in,out,camMat,disMat); jenv->ReleaseIntArrayElements(argb,pinPixels,0); //jenv->ReleaseIntArrayElements(pixels,poutPixels,0); returntrue; } /* *Class:ImgProc_ImageProc3 *Method:RgbMatUndistortMat *Signature:(JIIJ)Z */ JNIEXPORTjbooleanJNICALLJava_ImgProc_ImageProc3_RgbMatUndistortMat (JNIEnv*jenv,jclassjclassz,jlongpArgbMatAddr,jintwidth,jintheight,jlongpArgbOutMatAddr){ Matin=*((Mat*)pArgbMatAddr); Matout=*((Mat*)pArgbOutMatAddr); doublecam[]={width,0,width/2,0,height,height/2,0,0,1}; doubledistort[]={0.1,0.35,0.0,0.0,0.01}; MatcamMat=Mat(3,3,CV_64FC1,cam); MatdisMat=Mat(5,1,CV_64FC1,distort); undistort(in,out,camMat,disMat); returntrue; } /* *Class:ImgProc_ImageProc3 *Method:YuvNv21UndistortRgba *Signature:([BII[I)Z */ JNIEXPORTjbooleanJNICALLJava_ImgProc_ImageProc3_YuvNv21UndistortRgba (JNIEnv*jenv,jclassjclassz,jbyteArrayYuvNv21,jintwidth,jintheight,jintArraypixels){ jbyte*pBuf=(jbyte*)jenv->GetByteArrayElements(YuvNv21,0); jint*poutPixels=jenv->GetIntArrayElements(pixels,0); Matimage(height+height/2,width,CV_8UC1,(unsignedchar*)pBuf); Matrgba(height,width,CV_8UC4,(unsignedchar*)poutPixels); Mattmp(height,width,CV_8UC4); cvtColor(image,tmp,CV_YUV420sp2RGBA); doublecam[]={width,0,width/2,0,height,height/2,0,0,1}; doubledistort[]={0.1,0.35,0.0,0.0,0.01}; MatcamMat=Mat(3,3,CV_64FC1,cam); MatdisMat=Mat(5,1,CV_64FC1,distort); undistort(tmp,tmp,camMat,disMat); vector channels; split(tmp,channels); Matr=channels.at(0); Matg=channels.at(1); Matb=channels.at(2); Mata=channels.at(3); vector mbgr(4); mbgr[0]=b; mbgr[1]=g; mbgr[2]=r; mbgr[3]=a; merge(mbgr,rgba); jenv->ReleaseByteArrayElements(YuvNv21,pBuf,0); jenv->ReleaseIntArrayElements(pixels,poutPixels,0); returntrue; } /* *Class:ImgProc_ImageProc3 *Method:YuvNv21UndistortRgbaMat *Signature:([BIIJ)Z */ JNIEXPORTjbooleanJNICALLJava_ImgProc_ImageProc3_YuvNv21UndistortRgbaMat (JNIEnv*jenv,jclassjclassz,jbyteArrayYuvNv21,jintwidth,jintheight,jlongpMatAddr){ jbyte*pBuf=(jbyte*)jenv->GetByteArrayElements(YuvNv21,0); //jint*poutPixels=jenv->GetIntArrayElements(pixels,0); Matimage(height+height/2,width,CV_8UC1,(unsignedchar*)pBuf); //Matrgba(height,width,CV_8UC4,(unsignedchar*)poutPixels); Matrgba=*((Mat*)pMatAddr); Mattmp(height,width,CV_8UC4); cvtColor(image,tmp,CV_YUV420sp2RGBA); doublecam[]={width,0,width/2,0,height,height/2,0,0,1}; doubledistort[]={0.1,0.35,0.0,0.0,0.01}; MatcamMat=Mat(3,3,CV_64FC1,cam); MatdisMat=Mat(5,1,CV_64FC1,distort); undistort(tmp,tmp,camMat,disMat); vector channels; split(tmp,channels); Matr=channels.at(0); Matg=channels.at(1); Matb=channels.at(2); Mata=channels.at(3); vector mbgr(4); mbgr[0]=b; mbgr[1]=g; mbgr[2]=r; mbgr[3]=a; merge(mbgr,rgba); jenv->ReleaseByteArrayElements(YuvNv21,pBuf,0); //jenv->ReleaseIntArrayElements(pixels,poutPixels,0); returntrue; } #ifdef__cplusplus } #endif
以上这篇利用OPENCV为android开发畸变校正的JNI库方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。