Added intradocumentation.
This commit is contained in:
@@ -43,6 +43,12 @@ import com.badlogic.gdx.backends.android.AndroidApplication;
|
|||||||
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
|
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
|
||||||
import com.badlogic.gdx.controllers.mappings.Ouya;
|
import com.badlogic.gdx.controllers.mappings.Ouya;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>The main activity of the application.</p>
|
||||||
|
*
|
||||||
|
* <p>Provides operating system services to the LibGDX platform
|
||||||
|
* independant code, and handles OpenCV initialization and api calls.</p>
|
||||||
|
*/
|
||||||
public class MainActivity extends AndroidApplication implements OSFunctionalityProvider, CVProcessor{
|
public class MainActivity extends AndroidApplication implements OSFunctionalityProvider, CVProcessor{
|
||||||
private static final String TAG = "NXTAR_ANDROID_MAIN";
|
private static final String TAG = "NXTAR_ANDROID_MAIN";
|
||||||
private static final String CLASS_NAME = MainActivity.class.getSimpleName();
|
private static final String CLASS_NAME = MainActivity.class.getSimpleName();
|
||||||
@@ -62,6 +68,10 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
public native boolean findCalibrationPattern(long inMat, long outMat, float[] points);
|
public native boolean findCalibrationPattern(long inMat, long outMat, float[] points);
|
||||||
public native double calibrateCameraParameters(long camMat, long distMat, long frame, float[] calibrationPoints);
|
public native double calibrateCameraParameters(long camMat, long distMat, long frame, float[] calibrationPoints);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Static block. Tries to load OpenCV and the native method implementations
|
||||||
|
* statically if running on an OUYA device.</p>
|
||||||
|
*/
|
||||||
static{
|
static{
|
||||||
if(Ouya.runningOnOuya){
|
if(Ouya.runningOnOuya){
|
||||||
if(!OpenCVLoader.initDebug())
|
if(!OpenCVLoader.initDebug())
|
||||||
@@ -76,28 +86,41 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Initializes this activity</p>
|
||||||
|
*
|
||||||
|
* <p>This method handles the initialization of LibGDX and OpenCV. OpenCV is
|
||||||
|
* loaded the asynchronous method if the devices is not an OUYA console.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState){
|
public void onCreate(Bundle savedInstanceState){
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
cameraCalibrated = false;
|
cameraCalibrated = false;
|
||||||
|
|
||||||
|
// Set screen orientation. Portrait on mobile devices, landscape on OUYA.
|
||||||
if(!Ouya.runningOnOuya){
|
if(!Ouya.runningOnOuya){
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||||
}else{
|
}else{
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up the Android related variables.
|
||||||
uiHandler = new Handler();
|
uiHandler = new Handler();
|
||||||
uiContext = this;
|
uiContext = this;
|
||||||
wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
|
wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
|
||||||
|
|
||||||
|
// Attempt to initialize OpenCV.
|
||||||
if(!Ouya.runningOnOuya){
|
if(!Ouya.runningOnOuya){
|
||||||
|
// If running on a moble device, use the asynchronous method aided
|
||||||
|
// by the OpenCV Manager app.
|
||||||
loaderCallback = new BaseLoaderCallback(this){
|
loaderCallback = new BaseLoaderCallback(this){
|
||||||
@Override
|
@Override
|
||||||
public void onManagerConnected(int status){
|
public void onManagerConnected(int status){
|
||||||
switch(status){
|
switch(status){
|
||||||
case LoaderCallbackInterface.SUCCESS:
|
case LoaderCallbackInterface.SUCCESS:
|
||||||
|
// If successfully initialized then load the native method implementations and
|
||||||
|
// initialize the static matrices.
|
||||||
System.loadLibrary("cvproc");
|
System.loadLibrary("cvproc");
|
||||||
ocvOn = true;
|
ocvOn = true;
|
||||||
cameraMatrix = new Mat();
|
cameraMatrix = new Mat();
|
||||||
@@ -105,34 +128,46 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Toast.makeText(uiContext, R.string.ocv_failed, Toast.LENGTH_LONG).show();
|
Toast.makeText(uiContext, R.string.ocv_failed, Toast.LENGTH_LONG).show();
|
||||||
Gdx.app.exit();
|
ocvOn = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Launch the asynchronous initializer.
|
||||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_7, this, loaderCallback);
|
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_7, this, loaderCallback);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
if(!ocvOn){
|
// If running on an OUYA device.
|
||||||
Toast.makeText(uiContext, R.string.ocv_failed, Toast.LENGTH_LONG).show();
|
if(ocvOn){
|
||||||
}else{
|
// If OpenCV loaded successfully then initialize the native matrices.
|
||||||
cameraMatrix = new Mat();
|
cameraMatrix = new Mat();
|
||||||
distortionCoeffs = new Mat();
|
distortionCoeffs = new Mat();
|
||||||
|
}else{
|
||||||
|
Toast.makeText(uiContext, R.string.ocv_failed, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure LibGDX.
|
||||||
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
|
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
|
||||||
cfg.useGL20 = true;
|
cfg.useGL20 = true;
|
||||||
cfg.useAccelerometer = false;
|
cfg.useAccelerometer = false;
|
||||||
cfg.useCompass = false;
|
cfg.useCompass = false;
|
||||||
cfg.useWakelock = true;
|
cfg.useWakelock = true;
|
||||||
|
|
||||||
|
// Launch the LibGDX core game class.
|
||||||
initialize(new NxtARCore(this), cfg);
|
initialize(new NxtARCore(this), cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
// OSFunctionalityProvider interface methods. //
|
// OSFunctionalityProvider interface methods. //
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Implementation of the showShortToast method.</p>
|
||||||
|
*
|
||||||
|
* <p>Shows a short message on screen using Android's toast mechanism.</p>
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void showShortToast(final String msg){
|
public void showShortToast(final String msg){
|
||||||
uiHandler.post(new Runnable(){
|
uiHandler.post(new Runnable(){
|
||||||
@@ -143,6 +178,11 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Implementation of the showLongToast method.</p>
|
||||||
|
*
|
||||||
|
* <p>Shows a long message on screen using Android's toast mechanism.</p>
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void showLongToast(final String msg){
|
public void showLongToast(final String msg){
|
||||||
uiHandler.post(new Runnable(){
|
uiHandler.post(new Runnable(){
|
||||||
@@ -153,6 +193,11 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Implementation of the enableMulticast method.</p>
|
||||||
|
*
|
||||||
|
* <p>Enable the transmision and reception of multicast network messages.</p>
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void enableMulticast(){
|
public void enableMulticast(){
|
||||||
Gdx.app.log(TAG, CLASS_NAME + ".enableMulticast() :: Requesting multicast lock.");
|
Gdx.app.log(TAG, CLASS_NAME + ".enableMulticast() :: Requesting multicast lock.");
|
||||||
@@ -161,6 +206,11 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
multicastLock.acquire();
|
multicastLock.acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Implementation of the disableMulticast method.</p>
|
||||||
|
*
|
||||||
|
* <p>Disables the transmision and reception of multicast network messages.</p>
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void disableMulticast(){
|
public void disableMulticast(){
|
||||||
Gdx.app.log(TAG, CLASS_NAME + ".disableMulticast() :: Releasing multicast lock.");
|
Gdx.app.log(TAG, CLASS_NAME + ".disableMulticast() :: Releasing multicast lock.");
|
||||||
@@ -190,31 +240,33 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
if(ocvOn){
|
if(ocvOn){
|
||||||
int codes[] = new int[15];
|
int codes[] = new int[15];
|
||||||
Bitmap tFrame, mFrame;
|
Bitmap tFrame, mFrame;
|
||||||
|
|
||||||
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
|
||||||
|
|
||||||
Mat inImg = new Mat();
|
Mat inImg = new Mat();
|
||||||
Mat outImg = new Mat();
|
Mat outImg = new Mat();
|
||||||
|
|
||||||
|
// Decode the input image and convert it to an OpenCV matrix.
|
||||||
|
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
||||||
Utils.bitmapToMat(tFrame, inImg);
|
Utils.bitmapToMat(tFrame, inImg);
|
||||||
|
|
||||||
|
// Find up to 15 markers in the input image.
|
||||||
getMarkerCodesAndLocations(inImg.getNativeObjAddr(), outImg.getNativeObjAddr(), codes);
|
getMarkerCodesAndLocations(inImg.getNativeObjAddr(), outImg.getNativeObjAddr(), codes);
|
||||||
|
|
||||||
//Mat temp = new Mat();
|
// Encode the output image as a JPEG image.
|
||||||
//Imgproc.cvtColor(outImg, temp, Imgproc.COLOR_BGR2RGB);
|
|
||||||
|
|
||||||
mFrame = Bitmap.createBitmap(outImg.cols(), outImg.rows(), Bitmap.Config.RGB_565);
|
mFrame = Bitmap.createBitmap(outImg.cols(), outImg.rows(), Bitmap.Config.RGB_565);
|
||||||
Utils.matToBitmap(outImg, mFrame);
|
Utils.matToBitmap(outImg, mFrame);
|
||||||
mFrame.compress(CompressFormat.JPEG, 100, outputStream);
|
mFrame.compress(CompressFormat.JPEG, 100, outputStream);
|
||||||
|
|
||||||
|
// Create the output data structure.
|
||||||
CVMarkerData data = new CVMarkerData();
|
CVMarkerData data = new CVMarkerData();
|
||||||
data.outFrame = outputStream.toByteArray();
|
data.outFrame = outputStream.toByteArray();
|
||||||
data.markerCodes = codes;
|
data.markerCodes = codes;
|
||||||
|
|
||||||
|
// Clean up memory.
|
||||||
tFrame.recycle();
|
tFrame.recycle();
|
||||||
mFrame.recycle();
|
mFrame.recycle();
|
||||||
outputStream.reset();
|
outputStream.reset();
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
Gdx.app.debug(TAG, CLASS_NAME + ".findMarkersInFrame(): OpenCV is not ready or failed to load.");
|
Gdx.app.debug(TAG, CLASS_NAME + ".findMarkersInFrame(): OpenCV is not ready or failed to load.");
|
||||||
return null;
|
return null;
|
||||||
@@ -222,7 +274,17 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>Implementation of the findCalibrationPattern method.</p>
|
||||||
*
|
*
|
||||||
|
* <p>Attempts to detect a checkerboard calibration pattern in the input image.
|
||||||
|
* If the pattenr is found the method returns an image with the pattern
|
||||||
|
* highlighted and the spatial location of the calibration points in the
|
||||||
|
* output data structure.</p>
|
||||||
|
*
|
||||||
|
* @param frame The JPEG encoded input image.
|
||||||
|
* @return A data structure containing the processed output image and the
|
||||||
|
* location of the calibration points. If the pattern was not found, the returnd
|
||||||
|
* calibration points array is null.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public CVCalibrationData findCalibrationPattern(byte[] frame){
|
public CVCalibrationData findCalibrationPattern(byte[] frame){
|
||||||
@@ -255,6 +317,7 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
outputStream.reset();
|
outputStream.reset();
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
Gdx.app.debug(TAG, CLASS_NAME + ".findCalibrationPattern(): OpenCV is not ready or failed to load.");
|
Gdx.app.debug(TAG, CLASS_NAME + ".findCalibrationPattern(): OpenCV is not ready or failed to load.");
|
||||||
return null;
|
return null;
|
||||||
@@ -262,44 +325,9 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>Implementation of the calibrateCamera method.</p>
|
||||||
*
|
*
|
||||||
*/
|
* <p>Obtains the intrinsic camera parameters necesary for calibration.</p>
|
||||||
@Override
|
|
||||||
public byte[] undistortFrame(byte[] frame){
|
|
||||||
if(ocvOn){
|
|
||||||
byte undistortedFrame[];
|
|
||||||
Bitmap tFrame, mFrame;
|
|
||||||
Mat inImg = new Mat(), outImg = new Mat();
|
|
||||||
|
|
||||||
// Decode the input frame and convert it to an OpenCV Matrix.
|
|
||||||
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
|
||||||
Utils.bitmapToMat(tFrame, inImg);
|
|
||||||
|
|
||||||
// Apply the undistort correction to the input frame.
|
|
||||||
Imgproc.undistort(inImg, outImg, cameraMatrix, distortionCoeffs);
|
|
||||||
|
|
||||||
// Encode the output image as a JPEG image.
|
|
||||||
mFrame = Bitmap.createBitmap(outImg.cols(), outImg.rows(), Bitmap.Config.RGB_565);
|
|
||||||
Utils.matToBitmap(outImg, mFrame);
|
|
||||||
mFrame.compress(CompressFormat.JPEG, 100, outputStream);
|
|
||||||
|
|
||||||
// Prepare the return frame.
|
|
||||||
undistortedFrame = outputStream.toByteArray();
|
|
||||||
|
|
||||||
// Clean up memory.
|
|
||||||
tFrame.recycle();
|
|
||||||
mFrame.recycle();
|
|
||||||
outputStream.reset();
|
|
||||||
|
|
||||||
return undistortedFrame;
|
|
||||||
}else{
|
|
||||||
Gdx.app.debug(TAG, CLASS_NAME + ".undistortFrame(): OpenCV is not ready or failed to load.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void calibrateCamera(float[][] calibrationSamples, byte[] frame) {
|
public void calibrateCamera(float[][] calibrationSamples, byte[] frame) {
|
||||||
@@ -309,6 +337,8 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
Bitmap tFrame;
|
Bitmap tFrame;
|
||||||
Mat inImg = new Mat();
|
Mat inImg = new Mat();
|
||||||
|
|
||||||
|
// Save the calibration points on a one dimensional array for easier parameter passing
|
||||||
|
// to the native code.
|
||||||
for(int i = 0; i < ProjectConstants.CALIBRATION_SAMPLES; i++){
|
for(int i = 0; i < ProjectConstants.CALIBRATION_SAMPLES; i++){
|
||||||
for(int j = 0, p = 0; j < ProjectConstants.CALIBRATION_PATTERN_POINTS; j++, p += 2){
|
for(int j = 0, p = 0; j < ProjectConstants.CALIBRATION_PATTERN_POINTS; j++, p += 2){
|
||||||
calibrationPoints[p + (w * i)] = calibrationSamples[i][p];
|
calibrationPoints[p + (w * i)] = calibrationSamples[i][p];
|
||||||
@@ -316,13 +346,13 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode the input image and convert it to an OpenCV matrix.
|
||||||
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
||||||
Utils.bitmapToMat(tFrame, inImg);
|
Utils.bitmapToMat(tFrame, inImg);
|
||||||
|
|
||||||
|
// Attempt to obtain the camera parameters.
|
||||||
double error = calibrateCameraParameters(cameraMatrix.getNativeObjAddr(), distortionCoeffs.getNativeObjAddr(), inImg.getNativeObjAddr(), calibrationPoints);
|
double error = calibrateCameraParameters(cameraMatrix.getNativeObjAddr(), distortionCoeffs.getNativeObjAddr(), inImg.getNativeObjAddr(), calibrationPoints);
|
||||||
|
|
||||||
Gdx.app.log(TAG, CLASS_NAME + "calibrateCamera(): calibrateCameraParameters retured " + Double.toString(error));
|
Gdx.app.log(TAG, CLASS_NAME + "calibrateCamera(): calibrateCameraParameters retured " + Double.toString(error));
|
||||||
|
|
||||||
cameraCalibrated = true;
|
cameraCalibrated = true;
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
@@ -330,8 +360,59 @@ public class MainActivity extends AndroidApplication implements OSFunctionalityP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <p>Implementation of the undistorFrame method.</p>
|
||||||
*
|
*
|
||||||
|
* <p>Removes camera lens distortion from the input image using the
|
||||||
|
* camera parameters obtained by the calibrateCamera method.</p>
|
||||||
|
*
|
||||||
|
* @return A JPEG encoded image that is the input image after distortion correction. If the
|
||||||
|
* camera has not been calibrated or OpenCV failed to load returns null.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] undistortFrame(byte[] frame){
|
||||||
|
if(ocvOn){
|
||||||
|
if(cameraCalibrated){
|
||||||
|
byte undistortedFrame[];
|
||||||
|
Bitmap tFrame, mFrame;
|
||||||
|
Mat inImg = new Mat(), outImg = new Mat();
|
||||||
|
|
||||||
|
// Decode the input frame and convert it to an OpenCV Matrix.
|
||||||
|
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
||||||
|
Utils.bitmapToMat(tFrame, inImg);
|
||||||
|
|
||||||
|
// Apply the undistort correction to the input frame.
|
||||||
|
Imgproc.undistort(inImg, outImg, cameraMatrix, distortionCoeffs);
|
||||||
|
|
||||||
|
// Encode the output image as a JPEG image.
|
||||||
|
mFrame = Bitmap.createBitmap(outImg.cols(), outImg.rows(), Bitmap.Config.RGB_565);
|
||||||
|
Utils.matToBitmap(outImg, mFrame);
|
||||||
|
mFrame.compress(CompressFormat.JPEG, 100, outputStream);
|
||||||
|
|
||||||
|
// Prepare the return frame.
|
||||||
|
undistortedFrame = outputStream.toByteArray();
|
||||||
|
|
||||||
|
// Clean up memory.
|
||||||
|
tFrame.recycle();
|
||||||
|
mFrame.recycle();
|
||||||
|
outputStream.reset();
|
||||||
|
|
||||||
|
return undistortedFrame;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
Gdx.app.debug(TAG, CLASS_NAME + ".undistortFrame(): Camera has not been calibrated.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Gdx.app.debug(TAG, CLASS_NAME + ".undistortFrame(): OpenCV is not ready or failed to load.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Indicates if OpenCV has been sucessfully initialized and used
|
||||||
|
* to obtain the camera parameters for calibration.</p>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean cameraIsCalibrated() {
|
public boolean cameraIsCalibrated() {
|
||||||
|
Reference in New Issue
Block a user