17 กุมภาพันธ์ 2556

[Android Code] การทำให้กล้อง Auto Focus แบบอัตโนมัติ



และบทความคราวนี้ก็ยังคงอยู่ที่เรื่องกล้องอีกเหมือนเคย
กะจะลงเรื่องกล้องให้หมดที่เดียวไปเลย แล้วค่อยทำเรื่องอื่น

คราวนี้ก็จะเป็นเรื่องของการโฟกัสภาพอีกเช่นเคยน่ะแหละ
แต่จะเป็นการโฟกัสภาพโดยผู้ใช้ไม่ต้องกดเพื่อโฟกัสภาพ
ซึ่งการโฟกัสภาพก็จะใช้เป็นออโต้โฟกัสอีกนั่นแหละ
แต่ว่าจะให้ทำการโฟกัสก็ต่อเมื่อผู้ใช้ขยับตัวกล้องไปมา
ให้ลองนึกถึงแอพกล้องของแอนดรอยด์ 4.0 ขึ้นไป
ที่จะมีการปรับโฟกัสให้อัตโนมัติเมื่อเลื่อนหน้ากล้อง


แท้ที่จริงแล้ววิธีนี้อาจจะดูเหมือนซับซ้อน แต่จริงๆก็ไม่ยาก
เพราะใช้วิธีเช็คค่าจาก Accelerometer (วัดความเอียง)
เมื่อมีการขยับตัวเครื่องไปมา ค่าดังกล่าวจะมีการเปลี่ยนแปลง
ถ้าค่าเปลี่ยนมากกว่าที่กำหนด ก็ให้ทำการโฟกัสภาพใหม่

อ่ะ พอรู้วิธีแล้วก็ไม่ยากใช่มะล่ะ ก็เหลือแค่โค๊ดดังกล่าว

สำหรับเรื่องการใช้งาน Accelerometer ขอติดบทความไว้ก่อนนะ
ตั้งใจว่าจะทำอยู่เหมือนกัน แต่ยังไม่มีอารมณ์ทำเรื่องนั้น
ไว้ทำบทความอธิบายแล้วจะมาแปะลิ้งบทความให้ทีหลัง

หลักการก็ง่ายๆเลยคือค่าจาก Accelerometer เปลี่ยนแปลง
ก็จะให้ใช้คำสั่ง mCamera.autoFocus(AutofocusCallback cb)
ดังนั้นบทความนี้ก็ไม่มีอะไรมาก เพราะเคยอธิบายแล้ว ใน


เพราะฉะนั้นก็มาดูที่คำสั่งของบทความนี้เลยดีกว่า


Main.java
package app.akexorcist.cameraautofocus; import java.util.List; import android.hardware.Camera; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.Camera.AutoFocusCallback; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.Window; import android.view.WindowManager; public class Main extends Activity implements SurfaceHolder.Callback , SensorEventListener, AutoFocusCallback { Camera mCamera; SurfaceView mPreview; Sensor mAccelerometer; SensorManager mSensorManager; float motionX = 0; float motionY = 0; float motionZ = 0; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.main); mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); mPreview = (SurfaceView)findViewById(R.id.preview); mPreview.getHolder().addCallback(this); mPreview.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void onResume() { Log.d("System","onResume"); super.onResume(); mCamera = Camera.open(); mSensorManager.registerListener(this, mAccelerometer , SensorManager.SENSOR_DELAY_NORMAL); } public void onPause() { Log.d("System","onPause"); super.onPause(); mCamera.release(); mSensorManager.unregisterListener(this, mAccelerometer); } public void onAccuracyChanged(Sensor arg0, int arg1) { } public void onSensorChanged(SensorEvent event) { if(Math.abs(event.values[0] - motionX) > 1 || Math.abs(event.values[1] - motionY) > 1 || Math.abs(event.values[2] - motionZ) > 1 ) { Log.d("Camera System", "Refocus"); try { mCamera.autoFocus(this); } catch (RuntimeException e) { } motionX = event.values[0]; motionY = event.values[1]; motionZ = event.values[2]; } } public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { Log.d("CameraSystem","surfaceChanged"); Camera.Parameters params = mCamera.getParameters(); List<Camera.Size> previewSize = params.getSupportedPreviewSizes(); List<Camera.Size> pictureSize = params.getSupportedPictureSizes(); params.setPictureSize(pictureSize.get(0).width,pictureSize.get(0).height); params.setPreviewSize(previewSize.get(0).width,previewSize.get(0).height); params.setJpegQuality(100); mCamera.setParameters(params); try { mCamera.setPreviewDisplay(mPreview.getHolder()); mCamera.startPreview(); } catch (Exception e) { e.printStackTrace(); } } public void surfaceCreated(SurfaceHolder arg0) { } public void surfaceDestroyed(SurfaceHolder arg0) { } public void onAutoFocus(boolean success, Camera camera) { Log.d("CameraSystem","onAutoFocus"); } }

1. ประกาศตัวแปรสำหรับคลาส Sensor กับ SensorManger
เป็นคลาสที่เอาไว้ควบคุมการอ่านค่าจาก Accelerometer

2. ตัวแปรสำหรับเก็บค่าจาก Accelerometer แต่ละแกน XYZ
เอาไว้เป็นค่าเปรียบเทียบว่ามีการเคลื่อนที่ไปจากเดิมเท่าไร

3. กำหนดค่าให้กับตัวแปร mSensorManager และ mAccelerometer
เพื่อให้โปรแกรมสามารถใช้งานอ่านค่าจาก Accelerometer ได้

4. กำหนด Listener สำหรับอ่านค่าจาก Accelerometer
โดยให้ Listener ไปที่ Implement ไว้ว่า SensorEventListener



5. ยกเลิก Listener สำหรับอ่านค่าจาก Accelerometer
โดยจะให้ยกเลิก Listener ที่ทำการ Implement ไว้

6. ฟังก์ชัน Listener ของ Accelerometer เมื่อความแม่นยำเปลี่ยน
ซึ่งในตัวอย่างนี้จะไม่ได้ใช้อะไร เลยประกาศฟังก์ชันไว้เฉยๆ

7. ฟังก์ชัน Listener ของ Accelerometer เมื่อมีค่าเปลี่ยนแปลง
ซึ่งฟังก์ชันนี้แหละที่จะทำงานเมื่อผู้ใช้ขยับตัวเครื่อง
โดยที่ฟังก์ชันนี้จะสามารถอ่านค่าจาก Accelerometer ได้

8. ใช้ If เช็คว่าค่าแกน XYZ มีการเปลี่ยนแปลงไปมากกว่า 0.2 หรือไม่
ถ้ามากกว่าก็จะให้ทำการปรับโฟกัสใหม่ โดยที่ค่า 0.2 สามารถเปลี่ยนได้
ถ้ากำหนดค่าน้อยกว่า 0.2 เวลาขยับนิดหน่อยก็จะทำการโฟกัสใหม่
ถ้ากำหนดมากกว่า 0.2 ก็ต้องขยับตัวเครื่องมากหน่อยถึงจะโฟกัสใหม่
จากนั้นก็จะทำการอัพเดทเก็บค่าแกน XYZ ล่าสุดไว้ในตัวแปรทั้งสาม

9. ฟังก์ชัน Callback ของ Auto Focus ที่เคยอธิบายในบทความเก่าไปแล้ว


main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <SurfaceView
        android:id="@+id/preview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</RelativeLayout>


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.akexorcist.cameraautofocus"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="10" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher" >
        <activity
            android:name="Main"
            android:label="@string/app_name" 
            android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    
</manifest>


พอเสร็จแล้วก็ให้ลองทดสอบดู โดยการขยับตัวเครื่อง
ก็จะเห็นว่าตัวกล้องจะมีการปรับโฟกัสให้อัตโนมัติทันที

สำหรับผู้ที่หลงเข้ามาอ่านที่ต้องการไฟล์ตัวอย่างสามารถดาวน์โหลดได้จาก


เรื่องราวเก่าๆสำหรับกล้อง กล้อง และกล้อง





เหล่าพันธมิตรแอนดรอยด์

Devahoy Layer Net NuuNeoI The Cheese Factory Somkiat CC Mart Routine Artit-K Arnondora Kamonway Try to be android developer Oatrice Benz Nest Studios Kotchaphan@Medium Jirawatee@Medium Travispea@Medium