Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
cd152c3a
Commit
cd152c3a
authored
Oct 18, 2012
by
Konstantin Bezruk
Committed by
Andrey Kamaev
Oct 23, 2012
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Puzzle15 implementation with use of the OpenCV surface framework
parent
5f1339b3
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1019 additions
and
0 deletions
+1019
-0
.classpath
samples/android/15-puzzle-framework/.classpath
+8
-0
.project
samples/android/15-puzzle-framework/.project
+33
-0
AndroidManifest.xml
samples/android/15-puzzle-framework/AndroidManifest.xml
+31
-0
ic_launcher-web.png
samples/android/15-puzzle-framework/ic_launcher-web.png
+0
-0
android-support-v4.jar
...s/android/15-puzzle-framework/libs/android-support-v4.jar
+0
-0
ic_action_search.png
...5-puzzle-framework/res/drawable-hdpi/ic_action_search.png
+0
-0
ic_launcher.png
...oid/15-puzzle-framework/res/drawable-hdpi/ic_launcher.png
+0
-0
ic_launcher.png
...oid/15-puzzle-framework/res/drawable-ldpi/ic_launcher.png
+0
-0
ic_action_search.png
...5-puzzle-framework/res/drawable-mdpi/ic_action_search.png
+0
-0
ic_launcher.png
...oid/15-puzzle-framework/res/drawable-mdpi/ic_launcher.png
+0
-0
ic_action_search.png
...-puzzle-framework/res/drawable-xhdpi/ic_action_search.png
+0
-0
ic_launcher.png
...id/15-puzzle-framework/res/drawable-xhdpi/ic_launcher.png
+0
-0
activity_puzzle15.xml
...roid/15-puzzle-framework/res/layout/activity_puzzle15.xml
+12
-0
activity_puzzle15.xml
...ndroid/15-puzzle-framework/res/menu/activity_puzzle15.xml
+6
-0
strings.xml
samples/android/15-puzzle-framework/res/values/strings.xml
+11
-0
styles.xml
samples/android/15-puzzle-framework/res/values/styles.xml
+6
-0
OpenCvCameraBridgeViewBase.java
.../src/org/opencv/framework/OpenCvCameraBridgeViewBase.java
+320
-0
OpenCvJavaCameraView.java
...mework/src/org/opencv/framework/OpenCvJavaCameraView.java
+120
-0
OpenCvNativeCameraView.java
...work/src/org/opencv/framework/OpenCvNativeCameraView.java
+142
-0
Puzzle15Activity.java
...ork/src/org/opencv/samples/puzzle15/Puzzle15Activity.java
+127
-0
Puzzle15Processor.java
...rk/src/org/opencv/samples/puzzle15/Puzzle15Processor.java
+203
-0
No files found.
samples/android/15-puzzle-framework/.classpath
0 → 100644
View file @
cd152c3a
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry
kind=
"src"
path=
"src"
/>
<classpathentry
kind=
"src"
path=
"gen"
/>
<classpathentry
kind=
"con"
path=
"com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"
/>
<classpathentry
kind=
"con"
path=
"com.android.ide.eclipse.adt.LIBRARIES"
/>
<classpathentry
kind=
"output"
path=
"bin/classes"
/>
</classpath>
samples/android/15-puzzle-framework/.project
0 → 100644
View file @
cd152c3a
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>
15-puzzle
</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>
com.android.ide.eclipse.adt.ResourceManagerBuilder
</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>
com.android.ide.eclipse.adt.PreCompilerBuilder
</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>
org.eclipse.jdt.core.javabuilder
</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>
com.android.ide.eclipse.adt.ApkBuilder
</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>
com.android.ide.eclipse.adt.AndroidNature
</nature>
<nature>
org.eclipse.jdt.core.javanature
</nature>
</natures>
</projectDescription>
samples/android/15-puzzle-framework/AndroidManifest.xml
0 → 100644
View file @
cd152c3a
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
package=
"org.opencv.samples.puzzle15"
android:versionCode=
"1"
android:versionName=
"1.0"
>
<uses-permission
android:name=
"android.permission.CAMERA"
/>
<uses-feature
android:name=
"android.hardware.camera"
/>
<uses-feature
android:name=
"android.hardware.camera.autofocus"
/>
<uses-sdk
android:minSdkVersion=
"8"
android:targetSdkVersion=
"9"
/>
<application
android:icon=
"@drawable/ic_launcher"
android:label=
"@string/app_name"
android:theme=
"@style/AppTheme"
>
<activity
android:name=
".Puzzle15Activity"
android:label=
"@string/title_activity_puzzle15"
>
<intent-filter>
<action
android:name=
"android.intent.action.MAIN"
/>
<category
android:name=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
</application>
</manifest>
\ No newline at end of file
samples/android/15-puzzle-framework/ic_launcher-web.png
0 → 100644
View file @
cd152c3a
36.2 KB
samples/android/15-puzzle-framework/libs/android-support-v4.jar
0 → 100644
View file @
cd152c3a
File added
samples/android/15-puzzle-framework/res/drawable-hdpi/ic_action_search.png
0 → 100644
View file @
cd152c3a
3.05 KB
samples/android/15-puzzle-framework/res/drawable-hdpi/ic_launcher.png
0 → 100644
View file @
cd152c3a
2.94 KB
samples/android/15-puzzle-framework/res/drawable-ldpi/ic_launcher.png
0 → 100644
View file @
cd152c3a
1.47 KB
samples/android/15-puzzle-framework/res/drawable-mdpi/ic_action_search.png
0 → 100644
View file @
cd152c3a
2.96 KB
samples/android/15-puzzle-framework/res/drawable-mdpi/ic_launcher.png
0 → 100644
View file @
cd152c3a
1.92 KB
samples/android/15-puzzle-framework/res/drawable-xhdpi/ic_action_search.png
0 → 100644
View file @
cd152c3a
3.12 KB
samples/android/15-puzzle-framework/res/drawable-xhdpi/ic_launcher.png
0 → 100644
View file @
cd152c3a
3.91 KB
samples/android/15-puzzle-framework/res/layout/activity_puzzle15.xml
0 → 100644
View file @
cd152c3a
<LinearLayout
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"
>
<org.opencv.framework.OpenCvNativeCameraView
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
android:id=
"@+id/puzzle_activity_surface_view"
/>
</LinearLayout>
samples/android/15-puzzle-framework/res/menu/activity_puzzle15.xml
0 → 100644
View file @
cd152c3a
<menu
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<item
android:id=
"@+id/menu_start_new_game"
android:title=
"@string/menu_start_new_game"
android:orderInCategory=
"100"
/>
<item
android:id=
"@+id/menu_toggle_tile_numbers"
android:title=
"@string/menu_toggle_tile_numbers"
></item>
</menu>
samples/android/15-puzzle-framework/res/values/strings.xml
0 → 100644
View file @
cd152c3a
<resources>
<string
name=
"app_name"
>
15-puzzle
</string>
<string
name=
"hello_world"
>
Hello world!
</string>
<string
name=
"menu_settings"
>
Settings
</string>
<string
name=
"title_activity_puzzle15"
>
Puzzle15Activity
</string>
<string
name=
"menu_toggle_tile_numbers"
>
Show/hide tile numbers
</string>
<string
name=
"menu_start_new_game"
>
Start new game
</string>
</resources>
\ No newline at end of file
samples/android/15-puzzle-framework/res/values/styles.xml
0 → 100644
View file @
cd152c3a
<resources>
<style
name=
"AppTheme"
parent=
"android:Theme.Light"
/>
</resources>
\ No newline at end of file
samples/android/15-puzzle-framework/src/org/opencv/framework/OpenCvCameraBridgeViewBase.java
0 → 100644
View file @
cd152c3a
package
org
.
opencv
.
framework
;
import
java.util.List
;
import
org.opencv.android.Utils
;
import
org.opencv.core.Mat
;
import
org.opencv.core.Size
;
import
org.opencv.highgui.Highgui
;
import
org.opencv.highgui.VideoCapture
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.SurfaceHolder
;
import
android.view.SurfaceView
;
/**
* This is a basic class, implementing the interaction with Camera and OpenCV library.
* The main responsibility of it - is to control when camera can be enabled, process the frame,
* call external listener to make any adjustments to the frame and then draw the resulting
* frame to the screen.
* The clients shall implement CvCameraViewListener
* TODO: add method to control the format in which the frames will be delivered to CvCameraViewListener
*/
public
abstract
class
OpenCvCameraBridgeViewBase
extends
SurfaceView
implements
SurfaceHolder
.
Callback
{
private
static
final
int
MAX_UNSPECIFIED
=
-
1
;
protected
int
mFrameWidth
;
protected
int
mFrameHeight
;
protected
int
mMaxHeight
;
protected
int
mMaxWidth
;
private
Bitmap
mCacheBitmap
;
public
OpenCvCameraBridgeViewBase
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
getHolder
().
addCallback
(
this
);
mMaxWidth
=
MAX_UNSPECIFIED
;
mMaxHeight
=
MAX_UNSPECIFIED
;
}
public
interface
CvCameraViewListener
{
/**
* This method is invoked when camera preview has started. After this method is invoked
* the frames will start to be delivered to client via the onCameraFrame() callback.
* @param width - the width of the frames that will be delivered
* @param height - the height of the frames that will be delivered
*/
public
void
onCameraViewStarted
(
int
width
,
int
height
);
/**
* This method is invoked when camera preview has been stopped for some reason.
* No frames will be delivered via onCameraFrame() callback after this method is called.
*/
public
void
onCameraViewStopped
();
/**
* This method is invoked when delivery of the frame needs to be done.
* The returned values - is a modified frame which needs to be displayed on the screen.
* TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc)
*/
public
Mat
onCameraFrame
(
Mat
inputFrame
);
}
public
class
FrameSize
{
public
int
width
;
public
int
height
;
public
FrameSize
(
int
w
,
int
h
)
{
width
=
w
;
height
=
h
;
}
}
private
static
final
int
STOPPED
=
0
;
private
static
final
int
STARTED
=
1
;
private
static
final
String
TAG
=
"SampleCvBase"
;
private
CvCameraViewListener
mListener
;
private
int
mState
=
STOPPED
;
private
boolean
mEnabled
;
private
boolean
mSurfaceExist
;
private
Object
mSyncObject
=
new
Object
();
public
void
surfaceChanged
(
SurfaceHolder
arg0
,
int
arg1
,
int
arg2
,
int
arg3
)
{
synchronized
(
mSyncObject
)
{
if
(!
mSurfaceExist
)
{
mSurfaceExist
=
true
;
checkCurrentState
();
}
else
{
/** Surface changed. We need to stop camera and restart with new parameters */
/* Pretend that old surface has been destroyed */
mSurfaceExist
=
false
;
checkCurrentState
();
/* Now use new surface. Say we have it now */
mSurfaceExist
=
true
;
checkCurrentState
();
}
}
}
public
void
surfaceCreated
(
SurfaceHolder
holder
)
{
/* Do nothing. Wait until surfaceChanged delivered */
}
public
void
surfaceDestroyed
(
SurfaceHolder
holder
)
{
synchronized
(
mSyncObject
)
{
mSurfaceExist
=
false
;
checkCurrentState
();
}
}
/**
* This method is provided for clients, so they can enable the camera connection.
* The actuall onCameraViewStarted callback will be delivered only after both this method is called and surface is available
*/
public
void
enableView
()
{
synchronized
(
mSyncObject
)
{
mEnabled
=
true
;
checkCurrentState
();
}
}
/**
* This method is provided for clients, so they can disable camera connection and stop
* the delivery of frames eventhough the surfaceview itself is not destroyed and still stays on the scren
*/
public
void
disableView
()
{
synchronized
(
mSyncObject
)
{
mEnabled
=
false
;
checkCurrentState
();
}
}
public
void
setCvCameraViewListener
(
CvCameraViewListener
listener
)
{
mListener
=
listener
;
}
/**
* This method sets the maximum size that camera frame is allowed to be. When selecting
* size - the biggest size which less or equal the size set will be selected.
* As an example - we set setMaxFrameSize(200,200) and we have 176x152 and 320x240 sizes. The
* preview frame will be selected with 176x152 size.
* This method is usefull when need to restrict the size of preview frame for some reason (for example for video recording)
* @param maxWidth - the maximum width allowed for camera frame.
* @param maxHeight - the maxumum height allowed for camera frame
*/
public
void
setMaxFrameSize
(
int
maxWidth
,
int
maxHeight
)
{
mMaxWidth
=
maxWidth
;
mMaxHeight
=
maxHeight
;
}
/**
* Called when mSyncObject lock is held
*/
private
void
checkCurrentState
()
{
int
targetState
;
if
(
mEnabled
&&
mSurfaceExist
)
{
targetState
=
STARTED
;
}
else
{
targetState
=
STOPPED
;
}
if
(
targetState
!=
mState
)
{
/* The state change detected. Need to exit the current state and enter target state */
processExitState
(
mState
);
mState
=
targetState
;
processEnterState
(
mState
);
}
}
private
void
processEnterState
(
int
state
)
{
switch
(
state
)
{
case
STARTED:
onEnterStartedState
();
if
(
mListener
!=
null
)
{
mListener
.
onCameraViewStarted
(
mFrameWidth
,
mFrameHeight
);
}
break
;
case
STOPPED:
onEnterStoppedState
();
if
(
mListener
!=
null
)
{
mListener
.
onCameraViewStopped
();
}
break
;
};
}
private
void
processExitState
(
int
state
)
{
switch
(
state
)
{
case
STARTED:
onExitStartedState
();
break
;
case
STOPPED:
onExitStoppedState
();
break
;
};
}
private
void
onEnterStoppedState
()
{
/* nothing to do */
}
private
void
onExitStoppedState
()
{
/* nothing to do */
}
private
void
onEnterStartedState
()
{
connectCamera
(
getWidth
(),
getHeight
());
/* Now create cahe Bitmap */
mCacheBitmap
=
Bitmap
.
createBitmap
(
mFrameWidth
,
mFrameHeight
,
Bitmap
.
Config
.
ARGB_8888
);
}
private
void
onExitStartedState
()
{
disconnectCamera
();
if
(
mCacheBitmap
!=
null
)
{
mCacheBitmap
.
recycle
();
}
}
/**
* This method shall be called by the subclasses when they have valid
* object and want it to be delivered to external client (via callback) and
* then displayed on the screen.
* @param frame - the current frame to be delivered
*/
protected
void
deliverAndDrawFrame
(
Mat
frame
)
{
Mat
modified
;
if
(
mListener
!=
null
)
{
modified
=
mListener
.
onCameraFrame
(
frame
);
}
else
{
modified
=
frame
;
}
if
(
modified
!=
null
)
{
Utils
.
matToBitmap
(
modified
,
mCacheBitmap
);
}
if
(
mCacheBitmap
!=
null
)
{
Canvas
canvas
=
getHolder
().
lockCanvas
();
if
(
canvas
!=
null
)
{
canvas
.
drawBitmap
(
mCacheBitmap
,
(
canvas
.
getWidth
()
-
mCacheBitmap
.
getWidth
())
/
2
,
(
canvas
.
getHeight
()
-
mCacheBitmap
.
getHeight
())
/
2
,
null
);
getHolder
().
unlockCanvasAndPost
(
canvas
);
}
}
}
/**
* This method is invoked shall perform concrete operation to initialize the camera.
* CONTRACT: as a result of this method variables mFrameWidth and mFrameHeight MUST be
* initialized with the size of the Camera frames that will be delivered to external processor.
* @param width - the width of this SurfaceView
* @param height - the height of this SurfaceView
*/
protected
abstract
void
connectCamera
(
int
width
,
int
height
);
/**
* Disconnects and release the particular camera object beeing connected to this surface view.
* Called when syncObject lock is held
*/
protected
abstract
void
disconnectCamera
();
public
interface
ListItemAccessor
{
public
int
getWidth
(
Object
obj
);
public
int
getHeight
(
Object
obj
);
};
/**
* This helper method can be called by subclasses to select camera preview size.
* It goes over the list of the supported preview sizes and selects the maximum one which
* fits both values set via setMaxFrameSize() and surface frame allocated for this view
* @param supportedSizes
* @param surfaceWidth
* @param surfaceHeight
* @return
*/
protected
FrameSize
calculateCameraFrameSize
(
List
<?>
supportedSizes
,
ListItemAccessor
accessor
,
int
surfaceWidth
,
int
surfaceHeight
)
{
int
calcWidth
=
0
;
int
calcHeight
=
0
;
int
maxAllowedWidth
=
(
mMaxWidth
!=
MAX_UNSPECIFIED
&&
mMaxWidth
<
surfaceWidth
)?
mMaxWidth
:
surfaceWidth
;
int
maxAllowedHeight
=
(
mMaxHeight
!=
MAX_UNSPECIFIED
&&
mMaxHeight
<
surfaceHeight
)?
mMaxHeight
:
surfaceHeight
;
for
(
Object
size
:
supportedSizes
)
{
int
width
=
accessor
.
getWidth
(
size
);
int
height
=
accessor
.
getHeight
(
size
);
if
(
width
<=
maxAllowedWidth
&&
height
<=
maxAllowedHeight
)
{
if
(
width
>=
calcWidth
&&
height
>=
calcHeight
)
{
calcWidth
=
(
int
)
width
;
calcHeight
=
(
int
)
height
;
}
}
}
return
new
FrameSize
(
calcWidth
,
calcHeight
);
}
}
samples/android/15-puzzle-framework/src/org/opencv/framework/OpenCvJavaCameraView.java
0 → 100644
View file @
cd152c3a
package
org
.
opencv
.
framework
;
import
java.io.IOException
;
import
java.util.List
;
import
android.content.Context
;
import
android.graphics.ImageFormat
;
import
android.graphics.SurfaceTexture
;
import
android.hardware.Camera
;
import
android.hardware.Camera.PreviewCallback
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
org.opencv.core.CvType
;
import
org.opencv.core.Mat
;
import
org.opencv.core.MatOfByte
;
import
org.opencv.imgproc.Imgproc
;
/**
* This class is an implementation of the Bridge View between OpenCv and JAVA Camera.
* This class relays on the functionality available in base class and only implements
* required functions:
* connectCamera - opens Java camera and sets the PreviewCallback to be delivered.
* disconnectCamera - closes the camera and stops preview.
* When frame is delivered via callback from Camera - it processed via OpenCV to be
* converted to RGBA32 and then passed to the external callback for modifications if required.
*/
public
class
OpenCvJavaCameraView
extends
OpenCvCameraBridgeViewBase
implements
PreviewCallback
{
private
static
final
int
MAGIC_TEXTURE_ID
=
10
;
private
static
final
String
TAG
=
"OpenCvJavaCameraView"
;
private
Mat
mBaseMat
;
public
static
class
JavaCameraSizeAccessor
implements
ListItemAccessor
{
@Override
public
int
getWidth
(
Object
obj
)
{
Camera
.
Size
size
=
(
Camera
.
Size
)
obj
;
return
size
.
width
;
}
@Override
public
int
getHeight
(
Object
obj
)
{
Camera
.
Size
size
=
(
Camera
.
Size
)
obj
;
return
size
.
height
;
}
}
private
Camera
mCamera
;
public
OpenCvJavaCameraView
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
}
@Override
protected
void
connectCamera
(
int
width
,
int
height
)
{
mCamera
=
Camera
.
open
(
0
);
List
<
android
.
hardware
.
Camera
.
Size
>
sizes
=
mCamera
.
getParameters
().
getSupportedPreviewSizes
();
/* Select the size that fits surface considering maximum size allowed */
FrameSize
frameSize
=
calculateCameraFrameSize
(
sizes
,
new
JavaCameraSizeAccessor
(),
width
,
height
);
/* Now set camera parameters */
try
{
Camera
.
Parameters
params
=
mCamera
.
getParameters
();
List
<
Integer
>
formats
=
params
.
getSupportedPictureFormats
();
params
.
setPreviewFormat
(
ImageFormat
.
NV21
);
params
.
setPreviewSize
(
frameSize
.
width
,
frameSize
.
height
);
mCamera
.
setPreviewCallback
(
this
);
mCamera
.
setParameters
(
params
);
//mCamera.setPreviewTexture(new SurfaceTexture(MAGIC_TEXTURE_ID));
SurfaceTexture
tex
=
new
SurfaceTexture
(
MAGIC_TEXTURE_ID
);
mCamera
.
setPreviewTexture
(
tex
);
mFrameWidth
=
frameSize
.
width
;
mFrameHeight
=
frameSize
.
height
;
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
mBaseMat
=
new
Mat
(
mFrameHeight
+
(
mFrameHeight
/
2
),
mFrameWidth
,
CvType
.
CV_8UC1
);
/* Finally we are ready to start the preview */
mCamera
.
startPreview
();
}
@Override
protected
void
disconnectCamera
()
{
mCamera
.
setPreviewCallback
(
null
);
mCamera
.
stopPreview
();
mCamera
.
release
();
}
@Override
public
void
onPreviewFrame
(
byte
[]
frame
,
Camera
arg1
)
{
Log
.
i
(
TAG
,
"Preview Frame received. Need to create MAT and deliver it to clients"
);
Log
.
i
(
TAG
,
"Frame size is "
+
frame
.
length
);
mBaseMat
.
put
(
0
,
0
,
frame
);
Mat
frameMat
=
new
Mat
();
Imgproc
.
cvtColor
(
mBaseMat
,
frameMat
,
Imgproc
.
COLOR_YUV2RGBA_NV21
,
4
);
deliverAndDrawFrame
(
frameMat
);
frameMat
.
release
();
}
}
samples/android/15-puzzle-framework/src/org/opencv/framework/OpenCvNativeCameraView.java
0 → 100644
View file @
cd152c3a
package
org
.
opencv
.
framework
;
import
org.opencv.android.Utils
;
import
org.opencv.core.Mat
;
import
org.opencv.core.Size
;
import
org.opencv.highgui.Highgui
;
import
org.opencv.highgui.VideoCapture
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.util.AttributeSet
;
import
android.util.Log
;
/**
* This class is an implementation of a bridge between SurfaceView and native OpenCV camera.
* Due to the big amount of work done, by the base class this child is only responsible
* for creating camera, destroying camera and delivering frames while camera is enabled
*/
public
class
OpenCvNativeCameraView
extends
OpenCvCameraBridgeViewBase
{
public
static
final
String
TAG
=
"OpenCvNativeCameraView"
;
private
boolean
mStopThread
;
private
Thread
mThread
;
private
VideoCapture
mCamera
;
public
OpenCvNativeCameraView
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
}
@Override
protected
void
connectCamera
(
int
width
,
int
height
)
{
/* 1. We need to instantiate camera
* 2. We need to start thread which will be getting frames
*/
/* First step - initialize camera connection */
initializeCamera
(
getWidth
(),
getHeight
());
/* now we can start update thread */
mThread
=
new
Thread
(
new
CameraWorker
(
getWidth
(),
getHeight
()));
mThread
.
start
();
}
@Override
protected
void
disconnectCamera
()
{
/* 1. We need to stop thread which updating the frames
* 2. Stop camera and release it
*/
try
{
mStopThread
=
true
;
mThread
.
join
();
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
finally
{
mThread
=
null
;
mStopThread
=
false
;
}
/* Now release camera */
releaseCamera
();
}
public
static
class
OpenCvSizeAccessor
implements
ListItemAccessor
{
@Override
public
int
getWidth
(
Object
obj
)
{
Size
size
=
(
Size
)
obj
;
return
(
int
)
size
.
width
;
}
@Override
public
int
getHeight
(
Object
obj
)
{
Size
size
=
(
Size
)
obj
;
return
(
int
)
size
.
height
;
}
}
private
void
initializeCamera
(
int
width
,
int
height
)
{
mCamera
=
new
VideoCapture
(
Highgui
.
CV_CAP_ANDROID
);
//TODO: improve error handling
java
.
util
.
List
<
Size
>
sizes
=
mCamera
.
getSupportedPreviewSizes
();
/* Select the size that fits surface considering maximum size allowed */
FrameSize
frameSize
=
calculateCameraFrameSize
(
sizes
,
new
OpenCvSizeAccessor
(),
width
,
height
);
double
frameWidth
=
frameSize
.
width
;
double
frameHeight
=
frameSize
.
height
;
mCamera
.
set
(
Highgui
.
CV_CAP_PROP_FRAME_WIDTH
,
frameWidth
);
mCamera
.
set
(
Highgui
.
CV_CAP_PROP_FRAME_HEIGHT
,
frameHeight
);
mFrameWidth
=
(
int
)
frameWidth
;
mFrameHeight
=
(
int
)
frameHeight
;
Log
.
i
(
TAG
,
"Selected camera frame size = ("
+
mFrameWidth
+
", "
+
mFrameHeight
+
")"
);
}
private
void
releaseCamera
()
{
if
(
mCamera
!=
null
)
{
mCamera
.
release
();
}
}
private
class
CameraWorker
implements
Runnable
{
private
Mat
mRgba
=
new
Mat
();
private
int
mWidth
;
private
int
mHeight
;
CameraWorker
(
int
w
,
int
h
)
{
mWidth
=
w
;
mHeight
=
h
;
}
@Override
public
void
run
()
{
Mat
modified
;
do
{
if
(!
mCamera
.
grab
())
{
Log
.
e
(
TAG
,
"Camera frame grab failed"
);
break
;
}
mCamera
.
retrieve
(
mRgba
,
Highgui
.
CV_CAP_ANDROID_COLOR_FRAME_RGBA
);
deliverAndDrawFrame
(
mRgba
);
}
while
(!
mStopThread
);
}
}
}
samples/android/15-puzzle-framework/src/org/opencv/samples/puzzle15/Puzzle15Activity.java
0 → 100644
View file @
cd152c3a
package
org
.
opencv
.
samples
.
puzzle15
;
import
org.opencv.android.BaseLoaderCallback
;
import
org.opencv.android.LoaderCallbackInterface
;
import
org.opencv.android.OpenCVLoader
;
import
org.opencv.core.Mat
;
import
org.opencv.framework.OpenCvCameraBridgeViewBase.CvCameraViewListener
;
import
org.opencv.framework.OpenCvNativeCameraView
;
import
android.os.Bundle
;
import
android.app.Activity
;
import
android.util.Log
;
import
android.view.Menu
;
import
android.view.MenuItem
;
import
android.view.MotionEvent
;
import
android.view.Window
;
import
android.view.View
;
public
class
Puzzle15Activity
extends
Activity
implements
CvCameraViewListener
,
View
.
OnTouchListener
{
private
static
final
String
TAG
=
"Sample::Puzzle15::Activity"
;
private
OpenCvNativeCameraView
mOpenCvCameraView
;
private
Puzzle15Processor
mPuzzle15
;
private
int
mGameWidth
;
private
int
mGameHeight
;
private
BaseLoaderCallback
mLoaderCallback
=
new
BaseLoaderCallback
(
this
)
{
@Override
public
void
onManagerConnected
(
int
status
)
{
switch
(
status
)
{
case
LoaderCallbackInterface
.
SUCCESS
:
{
Log
.
i
(
TAG
,
"OpenCV loaded successfully"
);
mPuzzle15
=
new
Puzzle15Processor
();
mPuzzle15
.
prepareNewGame
();
/* Now enable camera view to start receiving frames */
mOpenCvCameraView
.
setOnTouchListener
(
Puzzle15Activity
.
this
);
mOpenCvCameraView
.
enableView
();
}
break
;
default
:
{
super
.
onManagerConnected
(
status
);
}
break
;
}
}
};
@Override
public
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
requestWindowFeature
(
Window
.
FEATURE_NO_TITLE
);
setContentView
(
R
.
layout
.
activity_puzzle15
);
mOpenCvCameraView
=
(
OpenCvNativeCameraView
)
findViewById
(
R
.
id
.
puzzle_activity_surface_view
);
mOpenCvCameraView
.
setCvCameraViewListener
(
this
);
OpenCVLoader
.
initAsync
(
OpenCVLoader
.
OPENCV_VERSION_2_4_2
,
this
,
mLoaderCallback
);
}
public
void
onDestroy
()
{
super
.
onDestroy
();
mOpenCvCameraView
.
disableView
();
}
@Override
public
boolean
onCreateOptionsMenu
(
Menu
menu
)
{
getMenuInflater
().
inflate
(
R
.
menu
.
activity_puzzle15
,
menu
);
return
true
;
}
@Override
public
boolean
onOptionsItemSelected
(
MenuItem
item
)
{
Log
.
i
(
TAG
,
"Menu Item selected "
+
item
);
if
(
item
.
getItemId
()
==
R
.
id
.
menu_start_new_game
)
{
/* We need to start new game */
mPuzzle15
.
prepareNewGame
();
}
else
if
(
item
.
getItemId
()
==
R
.
id
.
menu_toggle_tile_numbers
)
{
/* We need to enable or disable drawing of the tile numbers */
mPuzzle15
.
toggleTileNumbers
();
}
return
true
;
}
@Override
public
void
onCameraViewStarted
(
int
width
,
int
height
)
{
mGameWidth
=
width
;
mGameHeight
=
height
;
mPuzzle15
.
prepareGameSize
(
width
,
height
);
}
@Override
public
void
onCameraViewStopped
()
{
}
@Override
public
Mat
onCameraFrame
(
Mat
inputFrame
)
{
return
mPuzzle15
.
puzzleFrame
(
inputFrame
);
}
@Override
public
boolean
onTouch
(
View
view
,
MotionEvent
event
)
{
int
xpos
,
ypos
;
xpos
=
(
view
.
getWidth
()
-
mGameWidth
)
/
2
;
xpos
=
(
int
)
event
.
getX
()
-
xpos
;
ypos
=
(
view
.
getHeight
()
-
mGameHeight
)
/
2
;
ypos
=
(
int
)
event
.
getY
()
-
ypos
;
if
(
xpos
>=
0
&&
xpos
<=
mGameWidth
&&
ypos
>=
0
&&
ypos
<=
mGameHeight
)
{
/* click is inside the picture. Deliver this event to processor */
mPuzzle15
.
deliverTouchEvent
(
xpos
,
ypos
);
}
// TODO Auto-generated method stub
return
false
;
}
}
samples/android/15-puzzle-framework/src/org/opencv/samples/puzzle15/Puzzle15Processor.java
0 → 100644
View file @
cd152c3a
package
org
.
opencv
.
samples
.
puzzle15
;
import
org.opencv.core.Core
;
import
org.opencv.core.CvType
;
import
org.opencv.core.Mat
;
import
org.opencv.core.Scalar
;
import
org.opencv.core.Size
;
import
org.opencv.core.Point
;
import
android.util.Log
;
/**
* This class is a controller for puzzle game.
* It converts the image from Camera into the shuffled image
*/
public
class
Puzzle15Processor
{
private
static
final
int
GRID_SIZE
=
4
;
private
static
final
int
GRID_AREA
=
GRID_SIZE
*
GRID_SIZE
;
private
static
final
int
GRID_EMPTY_INDEX
=
GRID_AREA
-
1
;
private
static
final
String
TAG
=
"Puzzle15Processor"
;
private
int
[]
mIndexes
;
private
int
[]
mTextWidths
;
private
int
[]
mTextHeights
;
private
Mat
mRgba
;
private
Mat
mRgba15
;
private
Mat
[]
mCells
;
private
Mat
[]
mCells15
;
private
boolean
mShowTileNumbers
=
true
;
public
Puzzle15Processor
()
{
mTextWidths
=
new
int
[
GRID_AREA
];
mTextHeights
=
new
int
[
GRID_AREA
];
mIndexes
=
new
int
[
GRID_AREA
];
for
(
int
i
=
0
;
i
<
GRID_AREA
;
i
++)
{
Size
s
=
Core
.
getTextSize
(
Integer
.
toString
(
i
+
1
),
3
/* CV_FONT_HERSHEY_COMPLEX */
,
1
,
2
,
null
);
mTextHeights
[
i
]
=
(
int
)
s
.
height
;
mTextWidths
[
i
]
=
(
int
)
s
.
width
;
mIndexes
[
i
]
=
i
;
}
}
/* this method is intended to make processor prepared for a new game */
public
synchronized
void
prepareNewGame
()
{
do
{
shuffle
(
mIndexes
);
}
while
(!
isPuzzleSolvable
());
}
/* This method is to make the processor know the size of the frames that
* will be delivered via puzzleFrame.
* If the frames will be different size - then the result is unpredictable
*/
public
synchronized
void
prepareGameSize
(
int
width
,
int
height
)
{
mRgba15
=
new
Mat
(
height
,
width
,
CvType
.
CV_8UC4
);
mCells
=
new
Mat
[
GRID_AREA
];
mCells15
=
new
Mat
[
GRID_AREA
];
for
(
int
i
=
0
;
i
<
GRID_SIZE
;
i
++)
{
for
(
int
j
=
0
;
j
<
GRID_SIZE
;
j
++)
{
int
k
=
i
*
GRID_SIZE
+
j
;
// mCells[k] = mRgba.submat(i * height / GRID_SIZE, (i + 1) * height / GRID_SIZE, j * width / GRID_SIZE, (j + 1) * width / GRID_SIZE);
mCells15
[
k
]
=
mRgba15
.
submat
(
i
*
height
/
GRID_SIZE
,
(
i
+
1
)
*
height
/
GRID_SIZE
,
j
*
width
/
GRID_SIZE
,
(
j
+
1
)
*
width
/
GRID_SIZE
);
}
}
}
/* this method to be called from the outside. it processes the frame and shuffles
* the tiles as specified by mIndexes array
*/
public
synchronized
Mat
puzzleFrame
(
Mat
inputPicture
)
{
int
rows
=
inputPicture
.
rows
();
int
cols
=
inputPicture
.
cols
();
int
type
=
inputPicture
.
type
();
rows
=
rows
-
rows
%
4
;
cols
=
cols
-
cols
%
4
;
for
(
int
i
=
0
;
i
<
GRID_SIZE
;
i
++)
{
for
(
int
j
=
0
;
j
<
GRID_SIZE
;
j
++)
{
int
k
=
i
*
GRID_SIZE
+
j
;
mCells
[
k
]
=
inputPicture
.
submat
(
i
*
inputPicture
.
rows
()
/
GRID_SIZE
,
(
i
+
1
)
*
inputPicture
.
rows
()
/
GRID_SIZE
,
j
*
inputPicture
.
cols
()/
GRID_SIZE
,
(
j
+
1
)
*
inputPicture
.
cols
()
/
GRID_SIZE
);
}
}
rows
=
rows
-
rows
%
4
;
cols
=
cols
-
cols
%
4
;
// copy shuffled tiles
for
(
int
i
=
0
;
i
<
GRID_AREA
;
i
++)
{
int
idx
=
mIndexes
[
i
];
if
(
idx
==
GRID_EMPTY_INDEX
)
mCells15
[
i
].
setTo
(
new
Scalar
(
0x33
,
0x33
,
0x33
,
0xFF
));
else
{
mCells
[
idx
].
copyTo
(
mCells15
[
i
]);
if
(
mShowTileNumbers
)
{
Core
.
putText
(
mCells15
[
i
],
Integer
.
toString
(
1
+
idx
),
new
Point
((
cols
/
GRID_SIZE
-
mTextWidths
[
idx
])
/
2
,
(
rows
/
GRID_SIZE
+
mTextHeights
[
idx
])
/
2
),
3
/* CV_FONT_HERSHEY_COMPLEX */
,
1
,
new
Scalar
(
255
,
0
,
0
,
255
),
2
);
}
}
}
drawGrid
(
cols
,
rows
,
mRgba15
);
return
mRgba15
;
}
public
void
toggleTileNumbers
()
{
mShowTileNumbers
=
!
mShowTileNumbers
;
}
public
void
deliverTouchEvent
(
int
x
,
int
y
)
{
int
rows
=
mRgba15
.
rows
();
int
cols
=
mRgba15
.
cols
();
int
row
=
(
int
)
Math
.
floor
(
y
*
GRID_SIZE
/
rows
);
int
col
=
(
int
)
Math
.
floor
(
x
*
GRID_SIZE
/
cols
);
if
(
row
<
0
||
row
>=
GRID_SIZE
||
col
<
0
||
col
>=
GRID_SIZE
)
{
Log
.
e
(
TAG
,
"It is not expected to get touch event outside of picture"
);
return
;
}
int
idx
=
row
*
GRID_SIZE
+
col
;
int
idxtoswap
=
-
1
;
// left
if
(
idxtoswap
<
0
&&
col
>
0
)
if
(
mIndexes
[
idx
-
1
]
==
GRID_EMPTY_INDEX
)
idxtoswap
=
idx
-
1
;
// right
if
(
idxtoswap
<
0
&&
col
<
GRID_SIZE
-
1
)
if
(
mIndexes
[
idx
+
1
]
==
GRID_EMPTY_INDEX
)
idxtoswap
=
idx
+
1
;
// top
if
(
idxtoswap
<
0
&&
row
>
0
)
if
(
mIndexes
[
idx
-
GRID_SIZE
]
==
GRID_EMPTY_INDEX
)
idxtoswap
=
idx
-
GRID_SIZE
;
// bottom
if
(
idxtoswap
<
0
&&
row
<
GRID_SIZE
-
1
)
if
(
mIndexes
[
idx
+
GRID_SIZE
]
==
GRID_EMPTY_INDEX
)
idxtoswap
=
idx
+
GRID_SIZE
;
// swap
if
(
idxtoswap
>=
0
)
{
synchronized
(
this
)
{
int
touched
=
mIndexes
[
idx
];
mIndexes
[
idx
]
=
mIndexes
[
idxtoswap
];
mIndexes
[
idxtoswap
]
=
touched
;
}
}
}
private
void
drawGrid
(
int
cols
,
int
rows
,
Mat
drawMat
)
{
for
(
int
i
=
1
;
i
<
GRID_SIZE
;
i
++)
{
Core
.
line
(
drawMat
,
new
Point
(
0
,
i
*
rows
/
GRID_SIZE
),
new
Point
(
cols
,
i
*
rows
/
GRID_SIZE
),
new
Scalar
(
0
,
255
,
0
,
255
),
3
);
Core
.
line
(
drawMat
,
new
Point
(
i
*
cols
/
GRID_SIZE
,
0
),
new
Point
(
i
*
cols
/
GRID_SIZE
,
rows
),
new
Scalar
(
0
,
255
,
0
,
255
),
3
);
}
}
private
static
void
shuffle
(
int
[]
array
)
{
for
(
int
i
=
array
.
length
;
i
>
1
;
i
--)
{
int
temp
=
array
[
i
-
1
];
int
randIx
=
(
int
)
(
Math
.
random
()
*
i
);
array
[
i
-
1
]
=
array
[
randIx
];
array
[
randIx
]
=
temp
;
}
}
private
boolean
isPuzzleSolvable
()
{
int
sum
=
0
;
for
(
int
i
=
0
;
i
<
GRID_AREA
;
i
++)
{
if
(
mIndexes
[
i
]
==
GRID_EMPTY_INDEX
)
sum
+=
(
i
/
GRID_SIZE
)
+
1
;
else
{
int
smaller
=
0
;
for
(
int
j
=
i
+
1
;
j
<
GRID_AREA
;
j
++)
{
if
(
mIndexes
[
j
]
<
mIndexes
[
i
])
smaller
++;
}
sum
+=
smaller
;
}
}
return
sum
%
2
==
0
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment