Refactoring the image_pool for android, and adding some common utils for camera configuration. Also experimenting with optimization - grayscale preview is way faster than color right now.
parent
077dd77757
commit
3a932b0f6c
25 changed files with 1655 additions and 972 deletions
@ -1,2 +1,2 @@ |
|||||||
APP_ABI := armeabi armeabi-v7a
|
APP_ABI := $(ARM_TARGETS)
|
||||||
APP_MODULES := android-opencv
|
APP_MODULES := android-opencv
|
||||||
|
@ -1,98 +1,80 @@ |
|||||||
#include <string.h> |
#include <string.h> |
||||||
#include <jni.h> |
#include <jni.h> |
||||||
#include <yuv420sp2rgb.h> |
|
||||||
|
|
||||||
|
|
||||||
#ifndef max |
|
||||||
#define max(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) |
|
||||||
#define min(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) |
|
||||||
#endif |
|
||||||
|
|
||||||
|
|
||||||
|
#include <yuv420sp2rgb.h> |
||||||
|
|
||||||
/*
|
/*
|
||||||
YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved |
YUV 4:2:0 image with a plane of 8 bit Y samples followed by an interleaved |
||||||
U/V plane containing 8 bit 2x2 subsampled chroma samples. |
U/V plane containing 8 bit 2x2 subsampled chroma samples. |
||||||
except the interleave order of U and V is reversed. |
except the interleave order of U and V is reversed. |
||||||
|
|
||||||
H V |
H V |
||||||
Y Sample Period 1 1 |
Y Sample Period 1 1 |
||||||
U (Cb) Sample Period 2 2 |
U (Cb) Sample Period 2 2 |
||||||
V (Cr) Sample Period 2 2 |
V (Cr) Sample Period 2 2 |
||||||
*/ |
*/ |
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
size of a char: |
size of a char: |
||||||
find . -name limits.h -exec grep CHAR_BIT {} \; |
find . -name limits.h -exec grep CHAR_BIT {} \; |
||||||
*/ |
*/ |
||||||
|
|
||||||
|
#ifndef max |
||||||
|
#define max(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) |
||||||
|
#define min(a,b) ({typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) |
||||||
|
#endif |
||||||
|
|
||||||
const int bytes_per_pixel = 2; |
const int bytes_per_pixel = 2; |
||||||
void color_convert_common( |
void color_convert_common(unsigned char *pY, unsigned char *pUV, int width, int height, unsigned char *buffer, int grey) |
||||||
unsigned char *pY, unsigned char *pUV, |
|
||||||
int width, int height, unsigned char *buffer, |
|
||||||
int grey) |
|
||||||
{ |
{ |
||||||
int i, j; |
|
||||||
int nR, nG, nB; |
|
||||||
int nY, nU, nV; |
|
||||||
unsigned char *out = buffer; |
|
||||||
int offset = 0; |
|
||||||
|
|
||||||
if(grey){ |
int i, j; |
||||||
for (i = 0; i < height; i++) { |
int nR, nG, nB; |
||||||
for (j = 0; j < width; j++) { |
int nY, nU, nV; |
||||||
unsigned char nB = *(pY + i * width + j); |
unsigned char *out = buffer; |
||||||
|
int offset = 0; |
||||||
|
|
||||||
|
if (grey) |
||||||
|
{ |
||||||
|
memcpy(out,pY,width*height*sizeof(unsigned char)); |
||||||
|
} |
||||||
|
else |
||||||
|
// YUV 4:2:0
|
||||||
|
for (i = 0; i < height; i++) |
||||||
|
{ |
||||||
|
for (j = 0; j < width; j++) |
||||||
|
{ |
||||||
|
nY = *(pY + i * width + j); |
||||||
|
nV = *(pUV + (i / 2) * width + bytes_per_pixel * (j / 2)); |
||||||
|
nU = *(pUV + (i / 2) * width + bytes_per_pixel * (j / 2) + 1); |
||||||
|
|
||||||
|
// Yuv Convert
|
||||||
|
nY -= 16; |
||||||
|
nU -= 128; |
||||||
|
nV -= 128; |
||||||
|
|
||||||
|
if (nY < 0) |
||||||
|
nY = 0; |
||||||
|
|
||||||
out[offset++] = (unsigned char)nB; |
nB = (int)(1192 * nY + 2066 * nU); |
||||||
// out[offset++] = (unsigned char)nB;
|
nG = (int)(1192 * nY - 833 * nV - 400 * nU); |
||||||
// out[offset++] = (unsigned char)nB;
|
nR = (int)(1192 * nY + 1634 * nV); |
||||||
} |
|
||||||
} |
|
||||||
}else |
|
||||||
// YUV 4:2:0
|
|
||||||
for (i = 0; i < height; i++) { |
|
||||||
for (j = 0; j < width; j++) { |
|
||||||
nY = *(pY + i * width + j); |
|
||||||
nV = *(pUV + (i/2) * width + bytes_per_pixel * (j/2)); |
|
||||||
nU = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1); |
|
||||||
|
|
||||||
// Yuv Convert
|
|
||||||
nY -= 16; |
|
||||||
nU -= 128; |
|
||||||
nV -= 128; |
|
||||||
|
|
||||||
if (nY < 0) |
|
||||||
nY = 0; |
|
||||||
|
|
||||||
// nR = (int)(1.164 * nY + 2.018 * nU);
|
|
||||||
// nG = (int)(1.164 * nY - 0.813 * nV - 0.391 * nU);
|
|
||||||
// nB = (int)(1.164 * nY + 1.596 * nV);
|
|
||||||
|
|
||||||
nB = (int)(1192 * nY + 2066 * nU); |
|
||||||
nG = (int)(1192 * nY - 833 * nV - 400 * nU); |
|
||||||
nR = (int)(1192 * nY + 1634 * nV); |
|
||||||
|
|
||||||
nR = min(262143, max(0, nR)); |
|
||||||
nG = min(262143, max(0, nG)); |
|
||||||
nB = min(262143, max(0, nB)); |
|
||||||
|
|
||||||
|
|
||||||
nR >>= 10; nR &= 0xff; |
|
||||||
nG >>= 10; nG &= 0xff; |
|
||||||
nB >>= 10; nB &= 0xff; |
|
||||||
|
|
||||||
out[offset++] = (unsigned char)nR; |
nR = min(262143, max(0, nR)); |
||||||
out[offset++] = (unsigned char)nG; |
nG = min(262143, max(0, nG)); |
||||||
out[offset++] = (unsigned char)nB; |
nB = min(262143, max(0, nB)); |
||||||
|
|
||||||
//out[offset++] = 0xff; //set alpha for ARGB 8888 format
|
nR >>= 10; |
||||||
|
nR &= 0xff; |
||||||
|
nG >>= 10; |
||||||
|
nG &= 0xff; |
||||||
|
nB >>= 10; |
||||||
|
nB &= 0xff; |
||||||
|
|
||||||
|
out[offset++] = (unsigned char)nR; |
||||||
|
out[offset++] = (unsigned char)nG; |
||||||
|
out[offset++] = (unsigned char)nB; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
} |
} |
||||||
//offset = i * width * 3; //non power of two
|
|
||||||
//offset = i * texture_size + j;//power of two
|
|
||||||
//offset *= 3; //3 byte per pixel
|
|
||||||
//out = buffer + offset;
|
|
||||||
} |
|
||||||
}
|
|
||||||
|
@ -0,0 +1,11 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout |
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="fill_parent" |
||||||
|
android:orientation="vertical" |
||||||
|
android:gravity="center_vertical|center_horizontal"> |
||||||
|
<TextView android:scrollbars="vertical" android:id="@+id/calibtext" android:text="" android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" android:padding="20dip"/> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,40 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout |
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="fill_parent" |
||||||
|
android:orientation="vertical" |
||||||
|
android:gravity="center_vertical|center_horizontal"> |
||||||
|
<TextView android:text="@string/settings_text" android:autoLink="web" android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" android:padding="20dip"/> |
||||||
|
<LinearLayout android:id="@+id/LinearLayout01" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:gravity="center_vertical"> |
||||||
|
<TextView android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="@string/image_size_prompt"/> |
||||||
|
<Spinner android:id="@+id/image_size" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:saveEnabled="true" |
||||||
|
android:prompt="@string/image_size_prompt" |
||||||
|
android:entries="@array/image_sizes"> |
||||||
|
</Spinner> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout android:id="@+id/LinearLayout01" |
||||||
|
android:layout_width="wrap_content" android:layout_height="wrap_content" |
||||||
|
android:gravity="center_vertical"> |
||||||
|
<TextView android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" android:text="@string/camera_mode_prompt"/> |
||||||
|
<Spinner android:id="@+id/camera_mode" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:saveEnabled="true" |
||||||
|
android:prompt="@string/camera_mode_prompt" |
||||||
|
android:entries="@array/camera_mode"> |
||||||
|
</Spinner> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,40 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout |
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="fill_parent" |
||||||
|
android:orientation="vertical" |
||||||
|
android:gravity="center_vertical|center_horizontal"> |
||||||
|
<TextView android:text="@string/patterntext" android:autoLink="web" android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" android:padding="20dip"/> |
||||||
|
<LinearLayout android:id="@+id/LinearLayout01" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:gravity="center_vertical"> |
||||||
|
<TextView android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:text="Corners in width direction:"/> |
||||||
|
<Spinner android:id="@+id/rows" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:saveEnabled="true" |
||||||
|
android:prompt="@string/chesspromptx" |
||||||
|
android:entries="@array/chesssizes"> |
||||||
|
</Spinner> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
<LinearLayout android:id="@+id/LinearLayout01" |
||||||
|
android:layout_width="wrap_content" android:layout_height="wrap_content" |
||||||
|
android:gravity="center_vertical"> |
||||||
|
<TextView android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" android:text="Corners in height direction:"/> |
||||||
|
<Spinner android:id="@+id/cols" |
||||||
|
android:layout_width="fill_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:saveEnabled="true" |
||||||
|
android:prompt="@string/chessprompty" |
||||||
|
android:entries="@array/chesssizes"> |
||||||
|
</Spinner> |
||||||
|
</LinearLayout> |
||||||
|
|
||||||
|
</LinearLayout> |
@ -0,0 +1,11 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<resources> |
||||||
|
|
||||||
|
<declare-styleable name="CameraParams"> |
||||||
|
|
||||||
|
<attr name="preview_width" format="integer"/> |
||||||
|
<attr name="preview_height" format="integer"/> |
||||||
|
|
||||||
|
</declare-styleable> |
||||||
|
|
||||||
|
</resources> |
@ -0,0 +1,20 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<resources> |
||||||
|
<string-array name="chesssizes"> |
||||||
|
<item>3</item> |
||||||
|
<item>4</item> |
||||||
|
<item>5</item> |
||||||
|
<item>6</item> |
||||||
|
<item>7</item> |
||||||
|
<item>8</item> |
||||||
|
<item>9</item> |
||||||
|
<item>10</item> |
||||||
|
<item>11</item> |
||||||
|
<item>12</item> |
||||||
|
<item>13</item> |
||||||
|
</string-array> |
||||||
|
<string name="chesspromptx"> |
||||||
|
Choose the width:</string> |
||||||
|
<string name="chessprompty"> |
||||||
|
Choose the height:</string> |
||||||
|
</resources> |
@ -0,0 +1,20 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<resources> |
||||||
|
<string-array name="image_sizes"> |
||||||
|
<item>320x240</item> |
||||||
|
<item>400x300</item> |
||||||
|
<item>600x400</item> |
||||||
|
<item>800x600</item> |
||||||
|
<item>1000x800</item> |
||||||
|
</string-array> |
||||||
|
<string-array name="camera_mode"> |
||||||
|
<item>color</item> |
||||||
|
<item>BW</item> |
||||||
|
</string-array> |
||||||
|
<string name="image_size_prompt"> |
||||||
|
Image Size:\n(may not be exact) |
||||||
|
</string> |
||||||
|
<string name="camera_mode_prompt"> |
||||||
|
Camera Mode: |
||||||
|
</string> |
||||||
|
</resources> |
@ -0,0 +1,19 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<resources> |
||||||
|
<string name="app_name">Calibration</string> |
||||||
|
<string name="patternsize">Pattern Size</string> |
||||||
|
<string name="patterntext">Please choose the width and height (number of inside corners) of the checker |
||||||
|
board pattern you will be using for calibration. Default is 6 by 8 corners. You may find a checkerboard pattern at |
||||||
|
http://opencv.willowgarage.com/pattern</string> |
||||||
|
|
||||||
|
<string name="patternlink">http://opencv.willowgarage.com/pattern</string> |
||||||
|
<string name="camera_settings_label">Camera Settings</string> |
||||||
|
<string name="settings_text">Change the camera settings</string> |
||||||
|
|
||||||
|
<string name="calibration_service_started">Calibration calculations have started...</string> |
||||||
|
<string name="calibration_service_stopped">Calibration calculations has stopped.</string> |
||||||
|
<string name="calibration_service_finished">Calibration finished, you camera is calibrated.</string> |
||||||
|
<string name="calibration_service_label">Calibration</string> |
||||||
|
<string name="calibration_not_enough">Please capture atleast 10 images of the pattern!</string> |
||||||
|
|
||||||
|
</resources> |
@ -0,0 +1,47 @@ |
|||||||
|
package com.opencv.calibration; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.FileReader; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.text.method.ScrollingMovementMethod; |
||||||
|
import android.util.Log; |
||||||
|
import android.widget.TextView; |
||||||
|
|
||||||
|
import com.opencv.R; |
||||||
|
|
||||||
|
public class CalibrationViewer extends Activity { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onCreate(Bundle savedInstanceState) { |
||||||
|
// TODO Auto-generated method stub
|
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
setContentView(R.layout.calibrationviewer); |
||||||
|
|
||||||
|
Bundle extras = getIntent().getExtras(); |
||||||
|
String filename = extras.getString("calibfile"); |
||||||
|
if (filename != null) { |
||||||
|
TextView text = (TextView) findViewById(R.id.calibtext); |
||||||
|
text.setMovementMethod(new ScrollingMovementMethod()); |
||||||
|
try { |
||||||
|
BufferedReader reader = new BufferedReader(new FileReader( |
||||||
|
filename)); |
||||||
|
while (reader.ready()) { |
||||||
|
text.append(reader.readLine() +"\n"); |
||||||
|
} |
||||||
|
|
||||||
|
} catch (FileNotFoundException e) { |
||||||
|
Log.e("opencv", "could not open calibration file at:" |
||||||
|
+ filename); |
||||||
|
} catch (IOException e) { |
||||||
|
Log.e("opencv", "error reading file: " |
||||||
|
+ filename); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
package com.opencv.calibration; |
||||||
|
|
||||||
|
import com.opencv.R; |
||||||
|
import com.opencv.jni.Size; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.content.Context; |
||||||
|
import android.content.SharedPreferences; |
||||||
|
import android.content.SharedPreferences.Editor; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.view.View; |
||||||
|
import android.widget.AdapterView; |
||||||
|
import android.widget.AdapterView.OnItemSelectedListener; |
||||||
|
import android.widget.Spinner; |
||||||
|
|
||||||
|
public class ChessBoardChooser extends Activity { |
||||||
|
public static final String CHESS_SIZE = "chess_size"; |
||||||
|
public static final int DEFAULT_WIDTH = 6; |
||||||
|
public static final int DEFAULT_HEIGHT = 8; |
||||||
|
public static final int LOWEST = 3; |
||||||
|
|
||||||
|
class DimChooser implements OnItemSelectedListener { |
||||||
|
private String dim; |
||||||
|
|
||||||
|
public DimChooser(String dim) { |
||||||
|
this.dim = dim; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onItemSelected(AdapterView<?> arg0, View arg1, int pos, |
||||||
|
long arg3) { |
||||||
|
SharedPreferences settings = getSharedPreferences(CHESS_SIZE, 0); |
||||||
|
Editor editor = settings.edit(); |
||||||
|
editor.putInt(dim, pos + LOWEST); |
||||||
|
editor.commit(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onNothingSelected(AdapterView<?> arg0) { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onCreate(Bundle savedInstanceState) { |
||||||
|
// TODO Auto-generated method stub
|
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
setContentView(R.layout.chesssizer); |
||||||
|
// Restore preferences
|
||||||
|
SharedPreferences settings = getSharedPreferences(CHESS_SIZE, 0); |
||||||
|
int width = settings.getInt("width", 6); |
||||||
|
|
||||||
|
int height = settings.getInt("height", 8); |
||||||
|
|
||||||
|
Spinner wspin, hspin; |
||||||
|
wspin = (Spinner) findViewById(R.id.rows); |
||||||
|
hspin = (Spinner) findViewById(R.id.cols); |
||||||
|
|
||||||
|
wspin.setSelection(width - LOWEST); |
||||||
|
hspin.setSelection(height - LOWEST); |
||||||
|
|
||||||
|
wspin.setOnItemSelectedListener(new DimChooser("width")); |
||||||
|
hspin.setOnItemSelectedListener(new DimChooser("height")); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static Size getPatternSize(Context ctx) { |
||||||
|
SharedPreferences settings = ctx.getSharedPreferences(CHESS_SIZE, 0); |
||||||
|
int width = settings.getInt("width", 6); |
||||||
|
|
||||||
|
int height = settings.getInt("height", 8); |
||||||
|
|
||||||
|
return new Size(width, height); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,166 @@ |
|||||||
|
package com.opencv.calibration.services; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import android.app.Notification; |
||||||
|
import android.app.NotificationManager; |
||||||
|
import android.app.PendingIntent; |
||||||
|
import android.app.Service; |
||||||
|
import android.content.Intent; |
||||||
|
import android.os.Binder; |
||||||
|
import android.os.IBinder; |
||||||
|
import android.util.Log; |
||||||
|
import android.widget.Toast; |
||||||
|
|
||||||
|
|
||||||
|
import com.opencv.R; |
||||||
|
import com.opencv.calibration.CalibrationViewer; |
||||||
|
import com.opencv.calibration.Calibrator; |
||||||
|
import com.opencv.calibration.Calibrator.CalibrationCallback; |
||||||
|
|
||||||
|
|
||||||
|
public class CalibrationService extends Service implements CalibrationCallback { |
||||||
|
|
||||||
|
Class<?> activity; |
||||||
|
int icon; |
||||||
|
File calibration_file; |
||||||
|
public void startCalibrating(Class<?> activitycaller,int icon_id, Calibrator calibrator, File calibration_file) |
||||||
|
throws IOException { |
||||||
|
activity = activitycaller; |
||||||
|
icon = icon_id; |
||||||
|
// Display a notification about us starting. We put an icon in the
|
||||||
|
// status bar.
|
||||||
|
showNotification(); |
||||||
|
this.calibration_file = calibration_file; |
||||||
|
calibrator.setCallback(this); |
||||||
|
calibrator.calibrate(calibration_file); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private NotificationManager mNM; |
||||||
|
|
||||||
|
/** |
||||||
|
* Class for clients to access. Because we know this service always runs in |
||||||
|
* the same process as its clients, we don't need to deal with IPC. |
||||||
|
*/ |
||||||
|
public class CalibrationServiceBinder extends Binder { |
||||||
|
public CalibrationService getService() { |
||||||
|
return CalibrationService.this; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) { |
||||||
|
Log.i("LocalService", "Received start id " + startId + ": " + intent); |
||||||
|
// We want this service to continue running until it is explicitly
|
||||||
|
// stopped, so return sticky.
|
||||||
|
return START_NOT_STICKY; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onCreate() { |
||||||
|
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onDestroy() { |
||||||
|
// Cancel the persistent notification.
|
||||||
|
// mNM.cancel(R.string.calibration_service_started);
|
||||||
|
|
||||||
|
// Tell the user we stopped.
|
||||||
|
Toast.makeText(this, R.string.calibration_service_finished, |
||||||
|
Toast.LENGTH_SHORT).show(); |
||||||
|
} |
||||||
|
|
||||||
|
private final IBinder mBinder = new CalibrationServiceBinder(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public IBinder onBind(Intent intent) { |
||||||
|
return mBinder; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Show a notification while this service is running. |
||||||
|
*/ |
||||||
|
private void showNotification() { |
||||||
|
// In this sample, we'll use the same text for the ticker and the
|
||||||
|
// expanded notification
|
||||||
|
CharSequence text = getText(R.string.calibration_service_started); |
||||||
|
|
||||||
|
// Set the icon, scrolling text and timestamp
|
||||||
|
Notification notification = new Notification(icon, text, |
||||||
|
System.currentTimeMillis()); |
||||||
|
|
||||||
|
// The PendingIntent to launch our activity if the user selects this
|
||||||
|
// notification
|
||||||
|
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, |
||||||
|
new Intent(this, activity), 0); |
||||||
|
|
||||||
|
// Set the info for the views that show in the notification panel.
|
||||||
|
notification.setLatestEventInfo(this, |
||||||
|
getText(R.string.calibration_service_label), text, |
||||||
|
contentIntent); |
||||||
|
|
||||||
|
notification.defaults |= Notification.DEFAULT_SOUND; |
||||||
|
// Send the notification.
|
||||||
|
// We use a layout id because it is a unique number. We use it later to
|
||||||
|
// cancel.
|
||||||
|
mNM.notify(R.string.calibration_service_started, notification); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Show a notification while this service is running. |
||||||
|
*/ |
||||||
|
private void doneNotification() { |
||||||
|
// In this sample, we'll use the same text for the ticker and the
|
||||||
|
// expanded notification
|
||||||
|
CharSequence text = getText(R.string.calibration_service_finished); |
||||||
|
|
||||||
|
// Set the icon, scrolling text and timestamp
|
||||||
|
Notification notification = new Notification(icon, text, |
||||||
|
System.currentTimeMillis()); |
||||||
|
|
||||||
|
Intent intent = new Intent(this,CalibrationViewer.class); |
||||||
|
intent.putExtra("calibfile", calibration_file.getAbsolutePath()); |
||||||
|
// The PendingIntent to launch our activity if the user selects this
|
||||||
|
// notification
|
||||||
|
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, |
||||||
|
intent, 0); |
||||||
|
|
||||||
|
|
||||||
|
// Set the info for the views that show in the notification panel.
|
||||||
|
notification.setLatestEventInfo(this, |
||||||
|
getText(R.string.calibration_service_label), text, |
||||||
|
contentIntent); |
||||||
|
|
||||||
|
|
||||||
|
notification.defaults |= Notification.DEFAULT_SOUND; |
||||||
|
// Send the notification.
|
||||||
|
// We use a layout id because it is a unique number. We use it later to
|
||||||
|
// cancel.
|
||||||
|
mNM.notify(R.string.calibration_service_started, notification); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onFoundChessboard(Calibrator calibrator) { |
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onDoneCalibration(Calibrator calibration, File calibfile) { |
||||||
|
doneNotification(); |
||||||
|
stopSelf(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onFailedChessboard(Calibrator calibrator) { |
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,166 @@ |
|||||||
|
package com.opencv.camera; |
||||||
|
|
||||||
|
import com.opencv.R; |
||||||
|
|
||||||
|
import android.app.Activity; |
||||||
|
import android.content.Context; |
||||||
|
import android.content.SharedPreferences; |
||||||
|
import android.content.SharedPreferences.Editor; |
||||||
|
import android.os.Bundle; |
||||||
|
import android.view.View; |
||||||
|
import android.widget.AdapterView; |
||||||
|
import android.widget.AdapterView.OnItemSelectedListener; |
||||||
|
import android.widget.Spinner; |
||||||
|
|
||||||
|
public class CameraConfig extends Activity { |
||||||
|
public static final String CAMERA_SETTINGS = "CAMERA_SETTINGS"; |
||||||
|
public static final String CAMERA_MODE = "camera_mode"; |
||||||
|
public static final String IMAGE_WIDTH = "IMAGE_WIDTH"; |
||||||
|
public static final String IMAGE_HEIGHT = "IMAGE_HEIGHT"; |
||||||
|
public static final int CAMERA_MODE_BW = 0; |
||||||
|
public static final int CAMERA_MODE_COLOR = 1; |
||||||
|
|
||||||
|
public static int readCameraMode(Context ctx) { |
||||||
|
// Restore preferences
|
||||||
|
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS, |
||||||
|
0); |
||||||
|
int mode = settings.getInt(CAMERA_MODE, CAMERA_MODE_BW); |
||||||
|
return mode; |
||||||
|
} |
||||||
|
|
||||||
|
static public void setCameraMode(Context context, String mode) { |
||||||
|
int m = 0; |
||||||
|
if (mode.equals("BW")) { |
||||||
|
m = CAMERA_MODE_BW; |
||||||
|
} else if (mode.equals("color")) |
||||||
|
m = CAMERA_MODE_COLOR; |
||||||
|
setCameraMode(context, m); |
||||||
|
} |
||||||
|
|
||||||
|
private static String sizeToString(int[] size) { |
||||||
|
return size[0] + "x" + size[1]; |
||||||
|
} |
||||||
|
|
||||||
|
private static void parseStrToSize(String ssize, int[] size) { |
||||||
|
String sz[] = ssize.split("x"); |
||||||
|
size[0] = Integer.valueOf(sz[0]); |
||||||
|
size[1] = Integer.valueOf(sz[1]); |
||||||
|
} |
||||||
|
|
||||||
|
public static void readImageSize(Context ctx, int[] size) { |
||||||
|
// Restore preferences
|
||||||
|
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS, |
||||||
|
0); |
||||||
|
size[0] = settings.getInt(IMAGE_WIDTH, 600); |
||||||
|
size[1] = settings.getInt(IMAGE_HEIGHT, 600); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static void setCameraMode(Context ctx, int mode) { |
||||||
|
// Restore preferences
|
||||||
|
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS, |
||||||
|
0); |
||||||
|
Editor editor = settings.edit(); |
||||||
|
editor.putInt(CAMERA_MODE, mode); |
||||||
|
editor.commit(); |
||||||
|
} |
||||||
|
|
||||||
|
public static void setImageSize(Context ctx, String strsize) { |
||||||
|
int size[] = { 0, 0 }; |
||||||
|
parseStrToSize(strsize, size); |
||||||
|
setImageSize(ctx, size[0], size[1]); |
||||||
|
} |
||||||
|
|
||||||
|
public static void setImageSize(Context ctx, int width, int height) { |
||||||
|
// Restore preferences
|
||||||
|
SharedPreferences settings = ctx.getSharedPreferences(CAMERA_SETTINGS, |
||||||
|
0); |
||||||
|
Editor editor = settings.edit(); |
||||||
|
editor.putInt(IMAGE_WIDTH, width); |
||||||
|
editor.putInt(IMAGE_HEIGHT, height); |
||||||
|
editor.commit(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void onCreate(Bundle savedInstanceState) { |
||||||
|
// TODO Auto-generated method stub
|
||||||
|
super.onCreate(savedInstanceState); |
||||||
|
setContentView(R.layout.camerasettings); |
||||||
|
int mode = readCameraMode(this); |
||||||
|
int size[] = { 0, 0 }; |
||||||
|
readImageSize(this, size); |
||||||
|
|
||||||
|
final Spinner size_spinner; |
||||||
|
final Spinner mode_spinner; |
||||||
|
size_spinner = (Spinner) findViewById(R.id.image_size); |
||||||
|
mode_spinner = (Spinner) findViewById(R.id.camera_mode); |
||||||
|
|
||||||
|
String strsize = sizeToString(size); |
||||||
|
String strmode = modeToString(mode); |
||||||
|
|
||||||
|
String sizes[] = getResources().getStringArray(R.array.image_sizes); |
||||||
|
|
||||||
|
int i = 1; |
||||||
|
for (String x : sizes) { |
||||||
|
if (x.equals(strsize)) |
||||||
|
break; |
||||||
|
i++; |
||||||
|
} |
||||||
|
if(i <= sizes.length) |
||||||
|
size_spinner.setSelection(i-1); |
||||||
|
|
||||||
|
i = 1; |
||||||
|
String modes[] = getResources().getStringArray(R.array.camera_mode); |
||||||
|
for (String x :modes) { |
||||||
|
if (x.equals(strmode)) |
||||||
|
break; |
||||||
|
i++; |
||||||
|
} |
||||||
|
if(i <= modes.length) |
||||||
|
mode_spinner.setSelection(i-1); |
||||||
|
|
||||||
|
size_spinner.setOnItemSelectedListener(new OnItemSelectedListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onItemSelected(AdapterView<?> arg0, View spinner, |
||||||
|
int position, long arg3) { |
||||||
|
Object o = size_spinner.getItemAtPosition(position); |
||||||
|
if (o != null) |
||||||
|
setImageSize(spinner.getContext(), (String) o); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onNothingSelected(AdapterView<?> arg0) { |
||||||
|
|
||||||
|
} |
||||||
|
}); |
||||||
|
mode_spinner.setOnItemSelectedListener(new OnItemSelectedListener() { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onItemSelected(AdapterView<?> arg0, View spinner, |
||||||
|
int position, long arg3) { |
||||||
|
Object o = mode_spinner.getItemAtPosition(position); |
||||||
|
if (o != null) |
||||||
|
setCameraMode(spinner.getContext(), (String) o); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onNothingSelected(AdapterView<?> arg0) { |
||||||
|
|
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private String modeToString(int mode) { |
||||||
|
switch (mode) { |
||||||
|
case CAMERA_MODE_BW: |
||||||
|
return "BW"; |
||||||
|
case CAMERA_MODE_COLOR: |
||||||
|
return "color"; |
||||||
|
default: |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue