opencv4android–RGB2HSV
最近上班,工作强度不大,自己就找点东西学,正好碰见之前一个朋友面试,面试官出了一个题,自己闲着无聊也就研究研究,学习些新的东西。,先看一下题目。
题目中关键点估计就是opencv的hsv转换,说实话我当是也不知道那是什么东西,百度稍微了解下大致有了个思路。
- 调用相机拍照
- 将拍好的照片截图
- 配置opencv使用环境
- 调用opencv的方法
总体说来应该就这四步,前两步不难虽然我不会写,但是会百度啊,使用opencv就得自己研究了!
拍照加截图
百度了一圈,试了好几种方案,只有这个成功了,就用这个吧!思路是先调用相机,拍照返回后调用系统自带的截图,确定大小之后返回确定之后的uri。具体代码如下:
初始化一些常量
String path = getSDCardPath();
File file = new File(path + "/temp.jpg");
imageUri = Uri.fromFile(file);
File cropFile = new File(getSDCardPath() + "/temp_crop.jpg");
imageCropUri = Uri.fromFile(cropFile);
getSDcardPath方法
public static String getSDCardPath() {
String cmd = "cat /proc/mounts";
Runtime run = Runtime.getRuntime();
try {
Process p = run.exec(cmd);
BufferedInputStream in = new BufferedInputStream(p.getInputStream());
BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
String lineStr;
while ((lineStr = inBr.readLine()) != null) {
if (lineStr.contains("sdcard")
&& lineStr.contains(".android_secure")) {
String[] strArray = lineStr.split(" ");
if (strArray != null && strArray.length >= 5) {
String result = strArray[1].replace("/.android_secure",
"");
return result;
}
}
if (p.waitFor() != 0 && p.exitValue() == 1) {
}
}
inBr.close();
in.close();
} catch (Exception e) {
return Environment.getExternalStorageDirectory().getPath();
}
return Environment.getExternalStorageDirectory().getPath();
}
启动相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//action is capture
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, RESULT_CAMERA_ONLY);
启动截图
private void cropImg(Uri imageUri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(imageUri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 700);
intent.putExtra("outputY", 700);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageCropUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, RESULT_CAMERA_CROP_PATH_RESULT);
}
onActivityResult回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("TAG","onActivityResult");
if(resultCode!=RESULT_OK){
Toast.makeText(MainActivity.this,"ActivityResult resultCode error",Toast.LENGTH_SHORT).show();
return;
}
switch (requestCode) {
case RESULT_CAMERA_ONLY://拍照成功回调
cropImg(imageUri);
break;
case RESULT_CAMERA_CROP_PATH_RESULT://截图成功回调
Bundle extras = data.getExtras();
if (extras != null) {
try {
mBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageCropUri));
mImage.setImageBitmap(mBitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
主要的就是上面这些代码,先调用相机之后返回调用截图之后在返回,imageview加载由本地url生成的bitmap图像,这样钱两步就完成了。
配置opencv环境
opencv下载地址:
https://pan.baidu.com/s/1geNBqSV
本来是csdn的不过有点大就上传不了,目前版本是3.1,最新的。
不懂是什么东西的可以去百度。当然我百度完了也不明白是什么东西,大概了解是做图像处理的,反正特别XX就是了,先说一下集成环境,网上有很多方案不过都是很久以前的了,参考很多资料之后决定用这位大神的,简单明了。步步到位。
http://www.cnblogs.com/tail/p/4618476.html
最后一步测试成功什么的就不用了,咱们直接继续。
简单使用
网上很多都说需要什么NDK调用,也不会啊,不过上面的大神提到了在opencv3.0之后就可以非常简单的使用了,可以去参考sample中第一个例子。代码
@Override
protected void onResume() {
{
super.onResume();
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, mLoaderCallback);
} else {
Log.d("TAG", "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
}
复制粘贴之后会发现mLoaderCallback报错,因为没有嘛,还需要创建一个成员变量。
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i("TAG", "OpenCV loaded successfully");
/* Now enable camera view to start receiving frames */
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
运行的时候要是成功打印log了,说明之前的配置都是没有问题的。
接下来就是简单实用,因为要将RGB转化为HSV,简单百度下,没找到完成的例子,发现一个改变图片灰度的例子,于是尝试了一下。说一下具体步骤:
- 创建两个bitmap,一个用来保存变化之前的图像,一个用来保存变化之后的图像
- 创建两个图像对应的矩阵
- 使用opencv方法变成灰度图
- imageview显示
Mat rgbMat=new Mat();//rgb矩阵
Mat grayMat=new Mat();//gray矩阵
//灰度之后的Bitmap,mBitmap为RgbBitmap,之前已经赋过值了。
grayBitmap=Bitmap.createBitmap(mBitmap.getWidth(),mBitmap.getHeight(), Bitmap.Config.RGB_565);
Utils.bitmapToMat(mBitmap,rgbMat);//将图像转换为矩阵
Imgproc.cvtColor(rgbMat,grayMat,Imgproc.COLOR_RGB2GRAY);//矩阵变化
Utils.matToBitmap(grayMat,grayBitmap);//将矩阵转化为图像
mImage.setImageBitmap(grayBitmap);//显示图像
在敲的过程中可以发现,在矩阵变化的时候有很多种变化的方式,由于要使用RGB2HSV,正好也有这种模式就把COLOR_RGB2GRAY变成COLOR_RGB2HSV,也不知道这么写对不对,反正是有变化,已经让朋友给那个面试的人看了效果,准备再深入研究研究opencv,确实很强大啊!效果图:
可能有点卡,将就吧,等面试的那个人看看是不是想要的效果。