Controlling the Camera 控制相机

本文详细介绍了如何在Android中直接控制设备摄像头,从获取摄像头实例开始,到设置预览、修改相机参数、拍照以及释放资源的全过程。通过在不同线程中启动摄像头,并使用SurfaceView展示实时预览,实现高度定制化的相机应用。

Directly controlling a device camera requires a lot more code than requesting pictures or videos from existing camera applications. However, if you want to build a specialized camera application or something fully integrated in your app UI, http://blog.youkuaiyun.com/sergeycao

Open the Camera Object

Getting an instance of the Camera object is the first step in the process of directly controlling the camera. As Android's own Camera application does, the recommended way to access the camera is to open Camera on a separate thread that's launched from onCreate(). This approach is a good idea since it can take a while and might bog down the UI thread. In a more basic implementation, opening the camera can be deferred to the onResume() method to facilitate code reuse and keep the flow of control simple.

Calling Camera.open() throws an exception if the camera is already in use by another application, so we wrap it in a try block.

private boolean safeCameraOpen(int id) {
    boolean qOpened = false;
  
    try {
        releaseCameraAndPreview();
        mCamera = Camera.open(id);
        qOpened = (mCamera != null);
    } catch (Exception e) {
        Log.e(getString(R.string.app_name), "failed to open Camera");
        e.printStackTrace();
    }

    return qOpened;    
}

private void releaseCameraAndPreview() {
    mPreview.setCamera(null);
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

Since API level 9, the camera framework supports multiple cameras. If you use the legacy API and call open() without an argument, you get the first rear-facing camera.

Create the Camera Preview

Taking a picture usually requires that your users see a preview of their subject before clicking the shutter. To do so, you can use a SurfaceView to draw previews of what the camera sensor is picking up.

Preview Class

To get started with displaying a preview, you need preview class. The preview requires an implementation of the android.view.SurfaceHolder.Callback interface, which is used to pass image data from the camera hardware to the application.

class Preview extends ViewGroup implements SurfaceHolder.Callback {

    SurfaceView mSurfaceView;
    SurfaceHolder mHolder;

    Preview(Context context) {
        super(context);

        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
...
}

The preview class must be passed to the Camera object before the live image preview can be started, as shown in the next section.

Set and Start the Preview

A camera instance and its related preview must be created in a specific order, with the camera object being first. In the snippet below, the process of initializing the camera is encapsulated so that Camera.startPreview() is called by the setCamera() method, whenever the user does something to change the camera. The preview must also be restarted in the preview class surfaceChanged() callback method.

public void setCamera(Camera camera) {
    if (mCamera == camera) { return; }
    
    stopPreviewAndFreeCamera();
    
    mCamera = camera;
    
    if (mCamera != null) {
        List<Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
        mSupportedPreviewSizes = localSizes;
        requestLayout();
      
        try {
            mCamera.setPreviewDisplay(mHolder);
        } catch (IOException e) {
            e.printStackTrace();
        }
      
        /*
          Important: Call startPreview() to start updating the preview surface. Preview must 
          be started before you can take a picture.
          */
        mCamera.startPreview();
    }
}

Modify Camera Settings

Camera settings change the way that the camera takes pictures, from the zoom level to exposure compensation. This example changes only the preview size; see the source code of the Camera application for many more.

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    requestLayout();
    mCamera.setParameters(parameters);

    /*
      Important: Call startPreview() to start updating the preview surface. Preview must be
      started before you can take a picture.
    */
    mCamera.startPreview();
}

Set the Preview Orientation

Most camera applications lock the display into landscape mode because that is the natural orientation of the camera sensor. This setting does not prevent you from taking portrait-mode photos, because the orientation of the device is recorded in the EXIF header. The setCameraDisplayOrientation() method lets you change how the preview is displayed without affecting how the image is recorded. However, in Android prior to API level 14, you must stop your preview before changing the orientation and then restart it.

Take a Picture

Use the Camera.takePicture() method to take a picture once the preview is started. You can create Camera.PictureCallback and Camera.ShutterCallback objects and pass them into Camera.takePicture().

If you want to grab images continously, you can create a Camera.PreviewCallback that implements onPreviewFrame(). For something in between, you can capture only selected preview frames, or set up a delayed action to call takePicture().

Restart the Preview

After a picture is taken, you must restart the preview before the user can take another picture. In this example, the restart is done by overloading the shutter button.

@Override
public void onClick(View v) {
    switch(mPreviewState) {
    case K_STATE_FROZEN:
        mCamera.startPreview();
        mPreviewState = K_STATE_PREVIEW;
        break;

    default:
        mCamera.takePicture( null, rawCallback, null);
        mPreviewState = K_STATE_BUSY;
    } // switch
    shutterBtnConfig();
}

Stop the Preview and Release the Camera

Once your application is done using the camera, it's time to clean up. In particular, you must release the Camera object, or you risk crashing other applications, including new instances of your own application.

When should you stop the preview and release the camera? Well, having your preview surface destroyed is a pretty good hint that it’s time to stop the preview and release the camera, as shown in these methods from the Preview class.

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
        /*
          Call stopPreview() to stop updating the preview surface.
        */
        mCamera.stopPreview();
    }
}

/**
  * When this function returns, mCamera will be null.
  */
private void stopPreviewAndFreeCamera() {

    if (mCamera != null) {
        /*
          Call stopPreview() to stop updating the preview surface.
        */
        mCamera.stopPreview();
    
        /*
          Important: Call release() to release the camera for use by other applications. 
          Applications should release the camera immediately in onPause() (and re-open() it in
          onResume()).
        */
        mCamera.release();
    
        mCamera = null;
    }
}

Earlier in the lesson, this procedure was also part of the setCamera() method, so initializing a camera always begins with stopping the preview.

<think>好的,我现在需要帮助用户解决如何用C++控制海康威视工业相机和伺服电机的问题。首先,我得确定用户的具体需求是什么。他们可能是在做自动化项目,需要同时控制相机和电机,比如在视觉引导的机械臂系统中,相机捕捉位置,然后电机调整位置。 接下来,我需要考虑海康威视相机控制方式。根据之前的引用,海康威视的相机通常使用ONVIF协议或SDK。用户可能需要通过SDK来获取图像或控制相机参数。而伺服电机通常通过Modbus、EtherCAT或者特定的控制器指令来控制,比如使用RS485通信。 然后,我得回忆是否有相关的C++示例代码。海康威视的官网或开发者平台可能会有SDK和示例,用户可能需要先下载SDK,并按照文档配置环境。对于伺服电机,可能需要第三方库或者厂商提供的API,比如Modbus的库如libmodbus。 接下来,我需要组织一个基本的示例结构。可能需要分开相机控制和电机控制两部分。相机部分可能包括初始化、捕获图像、释放资源;电机部分包括连接、移动、断开。同时,需要处理错误情况,比如连接失败或指令执行错误。 需要注意的是,用户可能需要具体的SDK函数和电机协议细节,但如果没有具体型号和文档,代码只能是框架性的。因此,在回答中应该建议用户查阅官方文档,并确保包含必要的头文件和链接库。 另外,用户可能遇到的问题包括环境配置、SDK版本兼容性、通信协议的选择等。可能需要提醒用户注意这些方面,并提供获取帮助的途径,如官方支持或社区论坛。 最后,生成相关问题,帮助用户深入解决可能遇到的后续问题,比如性能优化、多线程处理、错误处理等。</think>[用户可见层] # 海康威视工业设备控制C++代码框架 ## 一、工业相机控制基础 海康威视工业相机需通过官方SDK进行控制开发流程包含: 1. 下载MVS开发套件(含Windows/Linux版) 2. 配置开发环境(需安装OpenCV等视觉库) 3. 使用SDK中的设备发现、图像采集API 示例代码框架: ```cpp #include "MvCameraControl.h" void CameraControl() { MV_CC_DEVICE_INFO_LIST stDeviceList; MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList); // 创建相机实例 void* handle = nullptr; MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[0]); // 连接设备 MV_CC_OpenDevice(handle); // 设置触发模式(示例为连续采集模式) MV_CC_SetEnumValue(handle, "TriggerMode", MV_TRIGGER_MODE_OFF); // 开始采集 MV_CC_StartGrabbing(handle); // 获取图像数据 MV_FRAME_OUT stImageInfo; MV_CC_GetImageBuffer(handle, &stImageInfo, 1000); // 处理图像... // 释放资源 MV_CC_StopGrabbing(handle); MV_CC_CloseDevice(handle); MV_CC_DestroyHandle(handle); } ``` ## 二、伺服电机控制基础 常见伺服控制方式(以Modbus-RTU为例): ```cpp #include <modbus.h> void ServoControl() { modbus_t* ctx = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1); modbus_set_slave(ctx, 1); // 设置从站地址 if(modbus_connect(ctx) == -1) { std::cerr << "Connection failed: " << modbus_strerror(errno); return; } // 写入目标位置(示例地址40001) uint16_t target_position = 1000; modbus_write_register(ctx, 0, target_position); // 读取当前位置 uint16_t current_pos; modbus_read_registers(ctx, 1, 1, &current_pos); modbus_close(ctx); modbus_free(ctx); } ``` ## 三、系统集成建议 1. 线程管理:建议使用独立线程处理图像采集和电机控制 2. 同步机制:通过共享内存/队列实现视觉坐标到电机位置的转换 3. 错误处理:增加超时重试和异常中断机制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值