原理简介
3D图片分为左右图和上下图,本程序的主要目的是将图片判断是左右图、上下图还是2D图片。原理采用灰度直方图匹配的方式,首先将图片分割为左右图,判断是否类似,然后将图片分割为上下图,判断是否类似,最终将得到的结果进行分析,得出最后结果。本程序中阈值选择为0.1.
代码实现
关键代码如下:
private static final String TAG = TDImageRecognition.class.getSimpleName();
public static final int LRMODEL = 1;
public static final int RLMODEL = 2;
public static final int TDMODEL = 3;
public static final int DTMODEL = 4;
public static final int SDMODEL = 5;
static {
try {
System.loadLibrary("tdimage");
} catch (UnsatisfiedLinkError use) {
Log.e(TAG, "WARNING: Could not load libtd_image.so");
}
}
public static int imageRecognition(Bitmap bitmap) {
if (bitmap == null)
return 0;
int w = bitmap.getWidth(), h = bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
int result = TDImageRecognition.tDImageRecognition(pix, w, h);
return result;
}
public static native int[] imageRecognition(int[] sourceImage, int w, int h);
public static native int tDImageRecognition(int[] sourceImage, int w, int h);
public static native int _getVideoType(String path);
通过JNI的方式调用OPENCV进行识别
JNIEXPORT jint JNICALL Java_com_runmit_imagerecognition_utils_TDImageRecognition_tDImageRecognition(
JNIEnv * env, jobject obj, jintArray buf, jint w, jint h) {
std::vector lrImages(2);
std::vector tdImages(2);
int* cbuf = env->GetIntArrayElements(buf, false);
IplImage* grayImage = changeArrayToGrayImage(cbuf, w, h);
//截取左边图片
IplImage* leftImage = splitImage(grayImage,w/2,h,0,0);
//截取右边图片
IplImage* rightImage = splitImage(grayImage,w/2,h,w/2,0);
//上面图片
IplImage* topImage = splitImage(grayImage,w,h/2,0,0);
//下面图片
IplImage* bottomImage = splitImage(grayImage,w,h/2,0,h/2);
double lrResult = calHist(leftImage,rightImage);
double tdResult = calHist(topImage,bottomImage);
cvReleaseImage(&grayImage);
cvReleaseImage(&leftImage);
cvReleaseImage(&rightImage);
cvReleaseImage(&topImage);
cvReleaseImage(&bottomImage);
if(lrResult <= THRESHOLD && tdResult > THRESHOLD) {
return LRMODEL;
}
if(lrResult > THRESHOLD && tdResult <= THRESHOLD) {
return TDMODEL;
}
return SDMODEL;
}
用到的帮助类
#include
#include
#include
#include "ImageUtils.h"
using namespace cv;
extern "C" {
//分割图片
IplImage* splitImage(IplImage* src, int w, int h, int origX,int origY ) {
if(src == NULL) {
return NULL;
printf("the image is null");
}
CvSize size= cvSize(w, h);//区域大小
cvSetImageROI(src,cvRect(origX,origY,size.width, size.height));//设置源图像ROI
IplImage* pDest = cvCreateImage(size,src->depth,src->nChannels);//创建目标图像
cvCopy(src,pDest); //复制图像
cvResetImageROI(src);//源图像用完后,清空ROI
return pDest;
}
//
double calHist(IplImage* img1,IplImage* img2){
int hist_size=256;
float range[] = {0,255};
float* ranges[]={range};
CvHistogram* gray_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
cvCalcHist(&img1,gray_hist,0,0);
CvHistogram* gray_hist2 = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
cvCalcHist(&img2,gray_hist2,0,0);
double result = cvCompareHist(gray_hist,gray_hist2,CV_COMP_BHATTACHARYYA);
cvReleaseImage(&img1);
cvReleaseImage(&img2);
cvReleaseHist(&gray_hist);
cvReleaseHist(&gray_hist2);
return result;
}
IplImage * change4channelTo3InIplImage(IplImage * src) {
if (src->nChannels != 4) {
return NULL;
}
IplImage * destImg = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);
for (int row = 0; row < src->height; row++) {
for (int col = 0; col < src->width; col++) {
CvScalar s = cvGet2D(src, row, col);
cvSet2D(destImg, row, col, s);
}
}
cvReleaseImage(&src);
return destImg;
}
IplImage* changeArrayToGrayImage(int* cbuf,int w,int h) {
if (cbuf == NULL) {
return 0;
}
Mat matImage(h, w, CV_8UC4, (unsigned char*) cbuf);
IplImage image = IplImage(matImage);
IplImage* image3channel = change4channelTo3InIplImage(&image);
IplImage* grayImage = cvCreateImage(cvGetSize(image3channel),IPL_DEPTH_8U,1);
cvCvtColor(image3channel,grayImage,CV_BGR2GRAY); //关键
//cvReleaseImage(&image);
cvReleaseImage(&image3channel);
return grayImage;
}
}
Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OpenCV_INSTALL_MODULES:=on
OPENCV_CAMERA_MODULES:=off
OPENCV_LIB_TYPE:=STATIC
#include ../includeOpenCV.mk
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
#try to load OpenCV.mk from default install location
include /home/wang1/Documents/opencv/OpenCV-3.1.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := tdimage
LOCAL_C_INCLUDES += core/include
LOCAL_SRC_FILES := \
core/ImageUtils.cpp \
core/TDImageRecognition.cpp \
LOCAL_LDLIBS += -lm -llog
include $(BUILD_SHARED_LIBRARY)
运行效果如下:
代码下载
http://download.csdn.net/detail/xiaowang0924/9456408