如何用Qt/C++访问Android摄像头

本文将讨论用Qt访问Android摄像头(或者说默认摄像头接口)所需要的步骤。很遗憾,自4.5版本以后OpenCV不再提供访问原生(Native C++)摄像头的库稳定方法,如果你想用Qt开发Android OpenCV程序的话,本文显然就是你要找的。强烈推荐你先阅读这篇文章(描述如何用Qt和Java代码混合编程)和这篇文章(如何用Qt打开Android图像库)然后再返回这里阅读,因为在此假设你已经熟悉这个流程。所以,如果你已经熟悉了用Qt访问Android图库,然后继续阅读下面描述的步子。


访问摄像头的方法和代码除了从AndroidManifest.xml文件开始以后的外,几乎所有的步子都跟访问Android图库一样。你可以通过在AndroidManifest.xml文件中添加如下代码添加摄像头访问许可。


   
   


    
    
   
   

下一步,需要你建一个简单的Qt函数来初始化Camera(capture)函数。Camera函数将采用Java程序实现,而在Qt C++程序中调用。就像这样:

QAndroidJniObject::callStaticMethod
   
   
    
    (“com/amin/QtAndroidCameraApp/QtAndroidCameraApp”,
“captureAnImage”,
“()V”);
   
   

注意QtAndroidCameraApp是我给出的名字,你可以按照你的app名称来自己命名。

再次,正如访问图库一样,需要写一个JNI函数类读取Java返回的selectedFileName变量,如下:

JNIEXPORT void JNICALL
Java_com_amin_QtAndroidCameraApp_QtAndroidCameraApp_fileSelected(JNIEnv */*env*/,
jobject /*obj*/,
jstring results)
{
selectedFileName = QAndroidJniObject(results).toString();
}

最后,需要在你的java代码中加入如下程序:

captureAnImage函数将会在C++程序中调用。它需要被声明成不带参数的静态函数:

static void captureAnImage()
{
m_instance.dispatchTakePictureIntent();
}



m_instance函数总是指向“this”类,调用 dispatchTakePictureIntent来启动摄像头接口:

private void dispatchTakePictureIntent()
{
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

// Ensure that there’s a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null)
{
// Create the File where the photo should go
File photoFile = null;
try
{
photoFile = m_instance.createImageFile();
}
catch (IOException ex)
{
// Error occurred while creating the File
Toast.makeText(QtAndroidCameraApp.this, ex.getLocalizedMessage(), Toast.LENGTH_LONG).show();
Toast.makeText(QtAndroidCameraApp.this, ex.getMessage(), Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null)
{
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));

lastCameraFileUri = photoFile.toString();

startActivityForResult(takePictureIntent, REQUEST_CAPTURE_IMAGE);
}
}
else
{
Toast.makeText(QtAndroidCameraApp.this, “Problems with your camera?!”, Toast.LENGTH_SHORT).show();
}
}
已更新:新增漏掉的函数createImageFile

上文提到的createImageFile函数需要这样定义:

private File createImageFile() throws IOException
{
// Create an image file name
String timeStamp = new SimpleDateFormat(“yyyyMMdd_HHmmss”).format(new Date());
String imageFileName = “MYAPPTEMP_” + timeStamp + “_”;
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, /* prefix */
“.jpg”, /* suffix */
storageDir /* directory */
);

return image;
}

尽管乍一看比较复杂,其实很简单。你启动摄像头然后等待它返回结果。如果返回结果正确,返回结果,在C++中将捕获这个,结果。否则,只需要显示一些错误信息并推出。可能你会注意到:dispatchTakePictureIntent调用了一些变量和函数,这些东西定义如下:


很明显第一个是lastCameraFileUri:

public String lastCameraFileUri;

接着是 REQUEST_CAPTURE_IMAGE,它你定义的一个常量,用以确保你在activity接收到的结果是摄像头拍出来的:

static final int REQUEST_CAPTURE_IMAGE = 1;


最后你需要override onActivityResult函数:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == RESULT_OK)
{
if(requestCode == REQUEST_CAPTURE_IMAGE)
{
String filePath = lastCameraFileUri;
fileSelected(filePath);
}
}
else
{
fileSelected(“:(“);
}

super.onActivityResult(requestCode, resultCode, data);
}

fileSelected函数需要被定义成native函数,因为就像你看到的,它从C++调用的文件名。唯一要做的事情就是做如下文的定义。函数的内容在你前面写的C++ Qt程序中

public static native void fileSelected(String fileName);

收工。 



  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值