Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • aricca/chessTrack
  • nicolas.furquez/chessTrack
2 results
Show changes
Commits on Source (36)
Showing
with 1479 additions and 653 deletions
This diff is collapsed.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="uy.edu.fing.chesstrack"
android:versionCode="1"
android:versionName="1.0" >
<!-- <application -->
<!-- android:allowBackup="true" -->
<!-- android:icon="@drawable/ic_launcher" -->
<!-- android:label="@string/app_name" -->
<!-- android:theme="@style/AppTheme" > -->
<!-- </application> -->
<application
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@drawable/ic_launcher"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<activity android:name="ChessTrackActivity"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<supports-screens android:resizeable="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="10" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
</manifest>
package uy.edu.chesstrack.communication;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import android.util.Log;
public class Client {
private static final String TAG = "CLIENT";
private static Client _clientInstance;
private Socket serverSocket;
private int _serverPort;
private String _serverIp;
//private BufferedReader input;
private DataOutputStream output;
protected Client(){
}
public static Client getInstance(){
if(_clientInstance == null){
_clientInstance = new Client();
}
return _clientInstance;
}
public void EstablishConnection(String serverIp, int serverPort) {
Log.i(TAG, "init client-server communication");
this._serverIp = serverIp;
this._serverPort = serverPort;
try {
InetAddress serverAddr = InetAddress.getByName(this._serverIp);
serverSocket = new Socket(serverAddr, _serverPort);
Log.i(TAG, "Server on " + this._serverIp + ":" + _serverPort);
// get stream to send data
this.output = new DataOutputStream(this.serverSocket.getOutputStream());
// get stream to receive data
//this.input = new BufferedReader(new InputStreamReader(this.serverSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
public void SendData(String msg) {
try {
Log.i(TAG, "sending="+ msg);
this.output.writeBytes(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
/*
public String ReceiveData() {
try {
String read = input.readLine();
Log.i(TAG, "received="+ read);
return read;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
*/
public void Stop() {
try {
//input.close();
output.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package uy.edu.fing.chesstrack;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener;
......@@ -8,15 +7,11 @@ import org.opencv.android.JavaCameraView;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import uy.edu.fing.chesstrack.communication.Client;
import uy.edu.fing.chesstrack.modulomodelador.Modelador;
import uy.edu.fing.chesstrack.modulovision.Adquisicion;
import uy.edu.fing.chesstrack.modulovision.Calibracion;
import uy.edu.fing.chesstrack.modulovision.Manager;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Bundle;
import android.text.Editable;
import android.util.Log;
......@@ -24,82 +19,69 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceView;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
public class ChessTrackActivity extends Activity implements CvCameraViewListener {
public class ChessTrackActivity extends Activity implements
CvCameraViewListener {
private static final String TAG = "CHESSTRACK::Activity";
private static final String IPV4_REGEX ="^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
private static final String PORT_REGEX ="^(\\d{4,5})$";
private static final String welcomeMSG = ""
+ "--------------------------------------------------------------------------\n"
+ " .:: CHESSTRACK ::. seguimiento de una partida de Ajedrez\n"
+ "\n"
+ " Aylen Ricca - Nicolas Furquez\n"
+ "--------------------------------------------------------------------------\n";
private CameraBridgeViewBase mOpenCvCameraView;
//private JavaCameraView mOpenCvCameraView;
private Adquisicion adq;
private Calibracion calibrar;
private Button btnCalibrar;
private Client ClientCommunication;
private MenuItem mItemCalibrar;
//TODO es chancho pero ver luego
private Mat frame;
private boolean isUsed;
private boolean isCalibrada ;
private final BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
private static final String IPV4_REGEX = "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
private static final String PORT_REGEX = "^(\\d{4,5})$";
// estados
private static final int IDLE = 0;
private static final int CALIBRAR = 1;
private static final int JUGAR = 2;
private CameraBridgeViewBase _mOpenCvCameraView;
// private JavaCameraView _mOpenCvCameraView;
private Manager _manager;
private MenuItem _mItemCalibrar;
private MenuItem _mItemServer;
private int _estado;
private final BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(
this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
case LoaderCallbackInterface.SUCCESS: {
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
} break;
default:
{
_mOpenCvCameraView.enableView();
}
break;
default: {
super.onManagerConnected(status);
} break;
}
break;
}
}
};
@Override
public void onResume()
{
public void onResume() {
super.onResume();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this, mLoaderCallback);
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this,
mLoaderCallback);
}
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.chess_track_layout);
mOpenCvCameraView = (JavaCameraView) findViewById(R.id.chess_track_layout);
mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
mOpenCvCameraView.setCvCameraViewListener(this);
Modelador.getInstance();
try {
isUsed = false;
isCalibrada =false;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
getServerIp();
_mOpenCvCameraView = (JavaCameraView) findViewById(R.id.chess_track_layout);
_mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
_mOpenCvCameraView.setCvCameraViewListener(this);
_manager = Manager.getInstance();
}
public void getServerIp(){
public void getServerIp() {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Communication Setup");
alert.setMessage("Set server ip");
......@@ -108,32 +90,26 @@ public class ChessTrackActivity extends Activity implements CvCameraViewListener
alert.setView(input);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
Editable value = input.getText();
if (value == null || value.toString().equals("") || !value.toString().matches(IPV4_REGEX)) {
Log.i(TAG,"INPUT= not valid IP" + value.toString());
if (value == null || value.toString().equals("")
|| !value.toString().matches(IPV4_REGEX)) {
Log.i(TAG, "INPUT= not valid IP" + value.toString());
getServerIp();
} else {
Log.i(TAG,"INPUT=" + value.toString());
Log.i(TAG,"IP=" + value.toString());
Log.i(TAG, "INPUT=" + value.toString());
Log.i(TAG, "IP=" + value.toString());
getServerPort(value.toString());
}
}
});
/*
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
// no server communication -- FIXME do not send info to client
}
});
*/
alert.show();
}
public void getServerPort(final String ip){
public void getServerPort(final String ip) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("Communication Setup");
alert.setMessage("Set server port");
......@@ -142,79 +118,64 @@ public class ChessTrackActivity extends Activity implements CvCameraViewListener
alert.setView(input);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int whichButton) {
Editable value = input.getText();
Log.i(TAG,"INPUT=" + value.toString());
if (value == null || value.toString().equals("") || !value.toString().matches(PORT_REGEX)) {
Log.i(TAG,"INPUT= not valid PORT" + value.toString());
Log.i(TAG, "INPUT=" + value.toString());
if (value == null || value.toString().equals("")
|| !value.toString().matches(PORT_REGEX)) {
Log.i(TAG, "INPUT= not valid PORT" + value.toString());
getServerPort(ip);
} else {
Log.i(TAG,"INPUT=" + value.toString());
Log.i(TAG, "INPUT=" + value.toString());
int port = Integer.parseInt(value.toString());
Log.i(TAG,"PORT=" + port);
//ClientCommunication = Client.getInstance();
//ClientCommunication.EstablishConnection(ip, port);
//ClientCommunication.SendData(welcomeMSG);
Log.i(TAG, "PORT=" + port);
_manager.setConnection(ip, port);
}
}
}
});
alert.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
Log.i(TAG, "called onCreateOptionsMenu");
mItemCalibrar = menu.add("Show/hide tile numbers");
_mItemCalibrar = menu.add("Calibrar..");
_mItemServer = menu.add("Conectar Server");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.i(TAG, "Menu Item selected " + item);
if (item == mItemCalibrar) {
isUsed = true;
if(frame!=null){
if (Calibracion.getInstance().calibrar(frame)){
ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50);
toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200); // 200 is duration in ms
try {
adq = new Adquisicion();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
isCalibrada = true;
}else{
ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50);
toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 700); // 200 is duration in ms
}
if (item == _mItemCalibrar) {
if (_estado == IDLE) {
_estado = CALIBRAR;
}
isUsed = false;
} else if (item == _mItemServer) {
getServerIp();
}
return true;
}
@Override
public void onPause()
{
public void onPause() {
super.onPause();
if (mOpenCvCameraView != null) {
mOpenCvCameraView.disableView();
if (_mOpenCvCameraView != null) {
_mOpenCvCameraView.disableView();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null) {
mOpenCvCameraView.disableView();
if (_mOpenCvCameraView != null) {
_mOpenCvCameraView.disableView();
}
if (this.ClientCommunication != null) {
this.ClientCommunication.Stop();
if (_manager != null) {
_manager.destroy();
}
}
......@@ -228,22 +189,24 @@ public class ChessTrackActivity extends Activity implements CvCameraViewListener
@Override
public Mat onCameraFrame(Mat inputFrame) {
// TODO MANEJAR ESTADOS
if (!isUsed){
frame = inputFrame;
}
if(isCalibrada){
Log.i(TAG, "calibrada");
inputFrame = adq.processFrame(inputFrame);
Modelador.getInstance().dividirTablero(inputFrame);
return Modelador.getInstance().dibujarEscaque();
//return inputFrame;
if (inputFrame != null) {
switch (_estado) {
case CALIBRAR:
Log.i(TAG, "calibrando...");
if (_manager.calibrar(inputFrame)) {
_estado = JUGAR;
} else {
_estado = IDLE;
}
break;
case JUGAR:
Log.i(TAG, "jugando...");
_manager.processFrame(inputFrame);
break;
case IDLE:
break;
}
}
return inputFrame;
}
}
package uy.edu.fing.chesstrack.ajedrez;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
public class Logica {
private static final String TAG = "CHESSTRACK::Logica";
private Mat _tableroInicio;
private Mat _tableroAnterior;
public Logica() {
double[] vectorONES = { 1, 1, 1, 1, 1, 1, 1, 1 };
_tableroInicio = Mat.zeros(new Size(8, 8), CvType.CV_8UC1);
_tableroInicio.put(0, 0, vectorONES);
_tableroInicio.put(1, 0, vectorONES);
_tableroInicio.put(6, 0, vectorONES);
_tableroInicio.put(7, 0, vectorONES);
_tableroAnterior = _tableroInicio;
}
public Mat getTableroInicio() {
return _tableroInicio;
}
public boolean validarNuevoTablero(Mat actual) {
Mat result = new Mat(8, 8, CvType.CV_8UC1);
Core.absdiff(actual, _tableroAnterior, result);
if (Core.countNonZero(result) != 0) {
_tableroAnterior = actual;
}
return (Core.countNonZero(result) != 0);
}
public boolean validarTableroArmado(Mat nuevo) {
Mat result = new Mat(8, 8, CvType.CV_8UC1);
Core.absdiff(nuevo, _tableroInicio, result);
return (Core.countNonZero(result) == 0);
}
}
......@@ -13,18 +13,18 @@ public class Client {
private static Client _clientInstance;
private Socket serverSocket;
private int _serverPort;
private String _serverIp;
private int _serverPort = 5556;
private String _serverIp = "192.168.1.23";
//private BufferedReader input;
// private BufferedReader input;
private DataOutputStream output;
protected Client(){
protected Client() {
}
public static Client getInstance(){
if(_clientInstance == null){
public static Client getInstance() {
if (_clientInstance == null) {
_clientInstance = new Client();
}
return _clientInstance;
......@@ -32,8 +32,8 @@ public class Client {
public void EstablishConnection(String serverIp, int serverPort) {
Log.i(TAG, "init client-server communication");
this._serverIp = serverIp;
this._serverPort = serverPort;
this._serverIp = serverIp;
this._serverPort = serverPort;
try {
Log.i(TAG, "Server on " + this._serverIp + ":" + _serverPort);
......@@ -41,10 +41,12 @@ public class Client {
serverSocket = new Socket(serverAddr, _serverPort);
// get stream to send data
this.output = new DataOutputStream(this.serverSocket.getOutputStream());
this.output = new DataOutputStream(
this.serverSocket.getOutputStream());
// get stream to receive data
//this.input = new BufferedReader(new InputStreamReader(this.serverSocket.getInputStream()));
// this.input = new BufferedReader(new
// InputStreamReader(this.serverSocket.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
}
......@@ -52,7 +54,7 @@ public class Client {
public void SendData(String msg) {
try {
Log.i(TAG, "sending="+ msg);
Log.i(TAG, "sending=" + msg);
this.output.writeBytes(msg);
} catch (IOException e) {
e.printStackTrace();
......@@ -60,21 +62,14 @@ public class Client {
}
/*
public String ReceiveData() {
try {
String read = input.readLine();
Log.i(TAG, "received="+ read);
return read;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
*/
* public String ReceiveData() { try { String read = input.readLine();
* Log.i(TAG, "received="+ read); return read; } catch (IOException e) {
* e.printStackTrace(); return null; } }
*/
public void Stop() {
try {
//input.close();
// input.close();
output.close();
serverSocket.close();
} catch (IOException e) {
......
package uy.edu.fing.chesstrack.modulomodelador;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import uy.edu.fing.chesstrack.modulovision.Calibracion;
import android.util.Log;
public class Modelador {
private static final String TAG = "CHESSTRACK::Modelador";
private final int CANT_FILAS= 8;
private final int CANT_SCAQUE = CANT_FILAS* CANT_FILAS;
private final int[][] tablero;
private final int CANT_FILAS = 8;
// private final int CANT_SCAQUE = CANT_FILAS * CANT_FILAS;
private final int MIN_CANT_PIX_WHITE = 30;
private Mat tablero;
// se cuentan de arrib a abajo y de izquierda a derecha
private final Mat[][] escaques;
private static Modelador instance;
// private static Modelador instance;
private Modelador(){
tablero = new int[CANT_FILAS][CANT_FILAS];
public Modelador() {
tablero = Mat.zeros(new Size(8, 8), CvType.CV_8UC1);
escaques = new Mat[CANT_FILAS][CANT_FILAS];
//TODO init tablero
}
public static Modelador getInstance(){
if (instance == null){
instance = new Modelador();
}
return instance;
}
public void dividirTablero(Mat inputFrame){
Rect roi = Calibracion.getInstance().getRectPOI();
Mat proccesFrame = inputFrame.submat(roi);
int largo = proccesFrame.rows();
int ancho = proccesFrame.cols();
public void dividirTablero(Mat inputFrame) {
Imgproc.cvtColor(inputFrame, inputFrame, Imgproc.COLOR_RGBA2GRAY, 4);
int largo = inputFrame.rows();
int ancho = inputFrame.cols();
// obtengo cuanto mide en ancho y largo un escaque
int largoEscaque = (int) Math.floor(largo /(CANT_FILAS+2) );//+1 porque se toma un escaque mas de borde
int anchoEscaque = (int) Math.floor(ancho /(CANT_FILAS+2) );
int largoEscaque = (int) Math.floor(largo / (CANT_FILAS + 2));// +2
// porque
// se
// toma
// un
// escaque
// mas
// de
// borde
int anchoEscaque = (int) Math.floor(ancho / (CANT_FILAS + 2));
Log.i(TAG, "largoEscaque= " + largoEscaque);
Log.i(TAG, "anchoEscaque= " + anchoEscaque);
for (int i = 0; i < 1; i++){
for (int j = 0; j < 1; j++){
int rowStart=(int)Math.floor(largoEscaque)+ i*largoEscaque;
int rowEnd = (int)Math.floor(largoEscaque)+i*largoEscaque + largoEscaque;
int colStart = (int)Math.floor(anchoEscaque)+j*anchoEscaque;
int colEnd = (int)Math.floor(anchoEscaque)+j*anchoEscaque + anchoEscaque;
escaques[i][j]= inputFrame.submat(colStart, colEnd,rowStart, rowEnd);
for (int i = 0; i < CANT_FILAS; i++) {
for (int j = 0; j < CANT_FILAS; j++) {
int rowStart = (int) Math.floor(largoEscaque) + i
* largoEscaque + 4;
int rowEnd = (int) Math.floor(largoEscaque) + i * largoEscaque
+ largoEscaque - 4;
int colStart = (int) Math.floor(anchoEscaque) + j
* anchoEscaque + 4;
int colEnd = (int) Math.floor(anchoEscaque) + j * anchoEscaque
+ anchoEscaque - 4;
escaques[i][j] = inputFrame.submat(colStart, colEnd, rowStart,
rowEnd);
}
}
}
private int getHayFichaEnEscaque(int i, int j) {
int ret = 0;
Mat mIntermediateMat = new Mat();
Imgproc.Sobel(escaques[i][j], mIntermediateMat, CvType.CV_8U, 1, 1);
Core.convertScaleAbs(mIntermediateMat, mIntermediateMat, 10, 0);
Imgproc.threshold(mIntermediateMat, mIntermediateMat, 70, 255,
Imgproc.THRESH_BINARY);
// int cant_pix = mIntermediateMat.cols() * mIntermediateMat.rows();
int cant_pix_white = Core.countNonZero(mIntermediateMat);
if (cant_pix_white > (MIN_CANT_PIX_WHITE)) {
ret = 1;
}
return ret;
}
public Mat getMatrizFichas(Mat frame) {
dividirTablero(frame);
tablero = Mat.zeros(new Size(8, 8), CvType.CV_8UC1);
for (int i = 0; i < CANT_FILAS; i++) {
for (int j = 0; j < CANT_FILAS; j++) {
tablero.put(i, j, getHayFichaEnEscaque(i, j));
}
}
return tablero.t();
}
public Mat dibujarEscaque() {
Mat tmp = Mat.ones(Calibracion.getInstance().get_sizeFrame(),
CvType.CV_8UC4);
Mat subm; // tmp.submat(new Rect(new Point(0,0)
// ,escaques[i][j].size()));
// escaques[i][j].copyTo(subm);
int pos_x = 0;
int pos_y = 0;
for (int i = 0; i < CANT_FILAS; i++) {
for (int j = 0; j < CANT_FILAS; j++) {
pos_x = (int) (escaques[i][j].size().width * i);
pos_y = (int) (escaques[i][j].size().height * j);
subm = tmp.submat(new Rect(new Point(pos_x, pos_y),
escaques[i][j].size()));
escaques[i][j].copyTo(subm);
Core.putText(tmp,
Integer.toString(i) + "-" + Integer.toString(j),
new Point(pos_x + 1, pos_y + 1),
Core.FONT_HERSHEY_SIMPLEX, 0.3, new Scalar(255, 0, 0));
}
}
return tmp;
}
public Mat dibujarEscaque(){
Mat tmp = Mat.ones(Calibracion.getInstance().getImagenCalibrada().size(), CvType.CV_8UC4);
Mat subm ; //tmp.submat(new Rect(new Point(0,0) ,escaques[i][j].size()));
//escaques[i][j].copyTo(subm);
int pos_x = 15;
int pos_y = 15;
for (int i = 0; i < 1; i++){
for (int j = 0; j < 1; j++){
subm = tmp.submat(new Rect(new Point(pos_x,pos_y) ,escaques[i][j].size()));
public Mat dibujarEscaquesCanny() {
Mat tmp = Mat.zeros(Calibracion.getInstance().get_sizeFrame(),
CvType.CV_8UC4);
Mat subm; // tmp.submat(new Rect(new Point(0,0)
// ,escaques[i][j].size()));
// escaques[i][j].copyTo(subm);
Mat mIntermediateMat = new Mat();
int pos_x = 0;
int pos_y = 0;
for (int i = 0; i < CANT_FILAS; i++) {
for (int j = 0; j < CANT_FILAS; j++) {
pos_x = (int) (escaques[i][j].size().width * i);
pos_y = (int) (escaques[i][j].size().height * j);
subm = tmp.submat(new Rect(new Point(pos_x, pos_y),
escaques[i][j].size()));
Imgproc.Canny(escaques[i][j], mIntermediateMat, 80, 90);
Imgproc.cvtColor(mIntermediateMat, subm,
Imgproc.COLOR_GRAY2RGBA, 4);
escaques[i][j].copyTo(subm);
pos_x = (int) (escaques[i][j].size().width*i +1);
pos_y = (int) (escaques[i][j].size().height*j +1);
Core.putText(tmp,
Integer.toString(i) + "-" + Integer.toString(j),
new Point(pos_x + 1, pos_y + 1),
Core.FONT_HERSHEY_SIMPLEX, 0.3, new Scalar(255, 0, 0));
}
}
return tmp;
}
public Mat dibujarEscaquesSobel(int version) {
Mat tmp = Mat.zeros(Calibracion.getRectROI().size(), CvType.CV_8UC4);
Mat subm; // tmp.submat(new Rect(new Point(0,0)
// ,escaques[i][j].size()));
// escaques[i][j].copyTo(subm);
Mat mIntermediateMat = new Mat();
int pos_x = 0;
int pos_y = 0;
Log.i(TAG, "cant_pix_INI");
for (int i = 0; i < CANT_FILAS; i++) {
for (int j = 0; j < CANT_FILAS; j++) {
pos_x = (int) (escaques[i][j].size().width * i);
pos_y = (int) (escaques[i][j].size().height * j);
subm = tmp.submat(new Rect(new Point(pos_x, pos_y),
escaques[i][j].size()));
// Imgproc.cvtColor(escaques[i][j] ,mIntermediateMat,
// Imgproc.COLOR_RGBA2GRAY,4);
Imgproc.Sobel(escaques[i][j], mIntermediateMat, CvType.CV_8U,
1, 1);
Core.convertScaleAbs(mIntermediateMat, mIntermediateMat, 10, 0);
Imgproc.threshold(mIntermediateMat, mIntermediateMat, 70, 255,
Imgproc.THRESH_BINARY);
Imgproc.erode(mIntermediateMat, mIntermediateMat, Imgproc
.getStructuringElement(Imgproc.MORPH_RECT, new Size(1,
1)));
Imgproc.dilate(mIntermediateMat, mIntermediateMat, Imgproc
.getStructuringElement(Imgproc.MORPH_RECT, new Size(1,
1)));
int cant_pix = mIntermediateMat.cols()
* mIntermediateMat.rows();
int cant_pix_white = Core.countNonZero(mIntermediateMat);
Log.i(TAG, "cant_pix=" + cant_pix);
Log.i(TAG, "cant_pix_white=" + cant_pix_white);
switch (version) {
case 1:
if (cant_pix_white > (MIN_CANT_PIX_WHITE)) {
Imgproc.cvtColor(mIntermediateMat, subm,
Imgproc.COLOR_GRAY2RGBA, 4);
} else {
Imgproc.cvtColor(escaques[i][j], subm,
Imgproc.COLOR_GRAY2RGBA, 4);
}
break;
case 2:
if (cant_pix_white > (MIN_CANT_PIX_WHITE)) {
Log.i(TAG, "NUEVA FICHA" + (i + 1) + "-" + (j + 1));
}
Imgproc.cvtColor(mIntermediateMat, subm,
Imgproc.COLOR_GRAY2RGBA, 4);
break;
default:
Imgproc.cvtColor(escaques[i][j], subm,
Imgproc.COLOR_GRAY2RGBA, 4);
break;
}
}
}
Log.i(TAG, "cant_pix_FIN");
return tmp;
}
......
package uy.edu.fing.chesstrack.modulovision;
import java.util.ArrayList;
import java.util.List;
import org.opencv.core.Mat;
import uy.edu.fing.chesstrack.modulovision.imgproc.BackgroundSupress;
import uy.edu.fing.chesstrack.modulovision.imgproc.Homografia;
import uy.edu.fing.chesstrack.modulovision.imgproc.ImgProcInterface;
import android.util.Log;
public class Adquisicion {
List<ImgProcInterface> listProc;
private static final String TAG = "CHESSTRACK::Adquisicion";
List<ImgProcInterface> _listProc;
public Adquisicion() throws Exception {
super();
Log.i(TAG, "Cargado....");
listProc = new ArrayList<ImgProcInterface>();
listProc.add( new Homografia());
//listProc.add( new EcualizarImagen());
//listProc.add( new SustraccionDeFondo());
//listProc.add( new BackgroundSupress());
_listProc = new ArrayList<ImgProcInterface>();
_listProc.add(new Homografia());
//_listProc.add(new EcualizarImagen());
}
/**
......@@ -41,12 +32,10 @@ public class Adquisicion {
*/
public synchronized Mat processFrame(Mat inputPicture) {
Log.i(TAG, "processFrame inicia");
Mat salida = inputPicture;
Mat prevImg = inputPicture;
for (ImgProcInterface proc: listProc){
prevImg = proc.procesarImagen(prevImg);
Mat tempImg = inputPicture;
for (ImgProcInterface proc: _listProc){
tempImg = proc.procesarImagen(tempImg);
}
return prevImg;
return tempImg;
}
}
......@@ -8,76 +8,64 @@ import org.opencv.core.Size;
import android.util.Log;
public class Calibracion {
private Mat imagenCalibrada;
private Mat imagenOriginal;
private MatOfPoint2f vertices;
public class Calibracion {
private static final String TAG = "CHESSTRACK::Calibracion";
private static Rect rectPOI = null;
private static Calibracion instance;
private Size _sizeFrame = null;
private MatOfPoint2f _vertices = null;
private static Rect _rectROI = null;
private static Calibracion _instance;
protected Calibracion(){
protected Calibracion() {
}
public static Calibracion getInstance(){
if(instance == null){
instance = new Calibracion();
public static Calibracion getInstance() {
if (_instance == null) {
_instance = new Calibracion();
}
return instance;
return _instance;
}
public boolean calibrar(Mat img){
public boolean calibrar(Mat img) {
Log.i(TAG, "INI calibrando");
boolean OK = false;
imagenOriginal = img;
imagenCalibrada = img;
Size patternSize = new Size(7,7);
Size patternSize = new Size(7, 7);
MatOfPoint2f corners = new MatOfPoint2f();
boolean ret = Calib3d.findChessboardCorners(imagenOriginal, patternSize, corners);
if (ret){
boolean ret = Calib3d.findChessboardCorners(img, patternSize, corners);
if (ret) {
Log.i(TAG, "Encontro = " + corners.total());
Log.i(TAG, "Encontro = " + corners.size().toString());
Calib3d.drawChessboardCorners(imagenCalibrada, patternSize, corners, ret);
vertices = corners;
// Calib3d.drawChessboardCorners(img, patternSize, corners, ret);
// only for debug
_vertices = corners;
_sizeFrame = img.size();
}
OK = ret;
Log.i(TAG, "FIN calibrando = " + ret);
return OK;
return ret;
}
public Mat getImagenCalibrada() {
return imagenCalibrada;
public Size get_sizeFrame() {
return _sizeFrame;
}
public void setImagenCalibrada(Mat imagenCalibrada) {
this.imagenCalibrada = imagenCalibrada;
public void set_sizeFrame(Size _sizeFrame) {
this._sizeFrame = _sizeFrame;
}
public MatOfPoint2f getVertices() {
return vertices;
return _vertices;
}
public void setVertices(MatOfPoint2f vertices) {
this.vertices = vertices;
this._vertices = vertices;
}
public static Rect getRectPOI() {
return rectPOI;
public static Rect getRectROI() {
return _rectROI;
}
public static void setRectPOI(Rect rectPOI) {
Calibracion.rectPOI = rectPOI;
public static void setRectROI(Rect rectROI) {
Calibracion._rectROI = rectROI;
}
}
package uy.edu.fing.chesstrack.modulovision;
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.imgproc.Imgproc;
import org.opencv.video.BackgroundSubtractorMOG2;
import android.util.Log;
public class DetectorOclusion {
private static final String TAG = "CHESSTRACK::BackgroundSupress";
private static final int OCLUSION = 0;
private static final int ESTABLE = 1;
private static final int TRANSICION = 2;
private static final int ENVIAR_TABLERO = 3;
private static final int START = -1;
private final Mat _fgMaskMOG2;
private Mat _resultado;
private BackgroundSubtractorMOG2 _pMOG2;
private final Mat _morphKernel;
private int _estadoANTERIOR;
private int _estadoACTUAL;
public DetectorOclusion() {
super();
Log.i(TAG, "constructor INI");
_morphKernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT,
new Size(3, 3));
_fgMaskMOG2 = new Mat(4, 1, CvType.CV_8UC1);
_pMOG2 = new BackgroundSubtractorMOG2();
_estadoACTUAL = START;
_resultado = new Mat();
Log.i(TAG, "constructor FIN");
}
public Mat get_resultado() {
return _resultado;
}
public void set_resultado(Mat _resultado) {
this._resultado = _resultado;
}
public boolean hayNuevoTableroValido(Mat inputFrame) {
/*
* if (_estadoACTUAL == START){ _pMOG2 = new BackgroundSubtractorMOG2();
* // MOG2 approach }
*/
Log.i(TAG, "Procesar!");
Log.i(TAG, "Region SIZE=" + inputFrame.size());
_pMOG2.apply(inputFrame, _fgMaskMOG2);
Imgproc.erode(_fgMaskMOG2, _fgMaskMOG2, _morphKernel);
Log.i(TAG, "Apply erode");
Imgproc.threshold(_fgMaskMOG2, _fgMaskMOG2, 200, 255,
Imgproc.THRESH_BINARY);
Log.i(TAG, "Apply threshold");
// Imgproc.dilate(_fgMaskMOG2, _fgMaskMOG2, _morphKernel);
// Log.i(TAG, "Apply dilate");
Scalar suma = Core.sumElems(_fgMaskMOG2);
Log.i(TAG, "SUMA = " + suma);
_estadoANTERIOR = _estadoACTUAL;
if (suma.val[0] > 1250000) {
Log.i(TAG, "VEO MANO !!!");
_estadoACTUAL = OCLUSION;
/*
* Core.putText(_fgMaskMOG2, "MANO !!!", new Point(20, 20),
* Core.FONT_HERSHEY_SIMPLEX, 0.8, new Scalar(255, 255, 0));
*/
} else {
if (_estadoANTERIOR == OCLUSION) {
/*
* Core.putText(_fgMaskMOG2, "TRANSI !!!", new Point(20, 20),
* Core.FONT_HERSHEY_SIMPLEX, 0.8, new Scalar(255, 255, 0));
*/
Log.i(TAG, "VEO TRANSICION !!!");
_estadoACTUAL = TRANSICION;
}
if (_estadoANTERIOR == TRANSICION) {
/*
* Core.putText(_fgMaskMOG2, "ESTABLE !!!", new Point(20, 20),
* Core.FONT_HERSHEY_SIMPLEX, 0.8, new Scalar(255, 255, 0));
*/
_estadoACTUAL = ENVIAR_TABLERO;
_pMOG2 = new BackgroundSubtractorMOG2(); // MOG2 approach
Log.i(TAG, "VEO ENVIAR !!!");
}
if (_estadoANTERIOR == ENVIAR_TABLERO) {
_estadoACTUAL = ESTABLE;
Log.i(TAG, "VEO ESTABLE !!!");
}
}
Log.i(TAG, "END");
Imgproc.cvtColor(_fgMaskMOG2, _resultado, Imgproc.COLOR_GRAY2RGBA, 4);
return (_estadoACTUAL == ENVIAR_TABLERO);
}
}
/*
* double maxArea = 0; MatOfPoint largestContour = null;
* Imgproc.findContours(_fgMaskMOG2, contours, new Mat(), Imgproc.RETR_LIST,
* Imgproc.CHAIN_APPROX_TC89_L1); for (MatOfPoint contour : contours) { double
* area = Imgproc.contourArea(contour); if (area > maxArea) { maxArea = area;
* largestContour = contour; } } Log.i(TAG, "ESTABLE !!!" + maxArea); if
* ((largestContour != null) && (maxArea > 10000)){ Log.i(TAG, "MANO !!!" +
* maxArea); Rect boundingRect = Imgproc.boundingRect(largestContour);
* ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50);
* toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200); // 200 is
* duration in ms }
*/
/*
* Imgproc.findContours(_fgMaskMOG2, contours, new Mat(), Imgproc.RETR_LIST,
* Imgproc.CHAIN_APPROX_NONE);
*
* for(int idx = 0; idx < contours.size(); idx++) { double area =
* Imgproc.contourArea(contours.get(idx)); Log.i(TAG, "CONTOUR = AREA: " +
* area); if ((area > 15000) && (area < 70000)){ Log.i(TAG, "DRAW !!! : " +
* area); Scalar color = new Scalar(255,127,127); Rect r =
* Imgproc.boundingRect(contours.get(idx)); Log.i(TAG,
* "3 at backgroundS "+(_fgMaskMOG2.type() == CvType.CV_8UC1));
* Core.rectangle(_fgMaskMOG2, r.tl(), r.br(), color, 2, 8, 0);
* //Imgproc.drawContours(_fgMaskMOG2, contours, idx, color); } }
*
* contours.clear();
*/
\ No newline at end of file
package uy.edu.fing.chesstrack.modulovision;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import uy.edu.fing.chesstrack.ajedrez.Logica;
import uy.edu.fing.chesstrack.communication.Client;
import uy.edu.fing.chesstrack.modulomodelador.Modelador;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.util.Log;
public class Manager {
private static final String TAG = "CHESSTRACK::MANAGER";
private static Manager _instance;
private static final int ARMANDO_TABLERO = 0;
private static final int JUGANDO = 1;
private static final int OK = 1;
private static final int NOT = 0;
private static final String WELCOME_MSG = ""
+ "--------------------------------------------------------------------------\n"
+ " .:: CHESSTRACK ::. seguimiento de una partida de Ajedrez\n"
+ "\n"
+ " TImag 2014\n"
+ " Nicolas Furquez - Aylen Ricca\n"
+ "--------------------------------------------------------------------------\n";
private static int _estado;
private static int _salida;
private static Adquisicion _adquisicion;
private static Client _client;
private static DetectorOclusion _detectorOclusion;
private static Modelador _modelador;
private static Logica _logica;
private final boolean _debug;
private int _cantJugada;
protected Manager() {
_estado = ARMANDO_TABLERO;
_salida = NOT;
_adquisicion = null;
_client = null;
_debug = false;
_cantJugada = 0;
}
public static Manager getInstance() {
if (_instance == null) {
_instance = new Manager();
}
return _instance;
}
public static int get_estado() {
return _estado;
}
public static void set_estado(int _estado) {
Manager._estado = _estado;
}
public void setConnection(String ip, int port) {
Log.i(TAG, "Setting connection");
_client = Client.getInstance();
_client.EstablishConnection(ip, port);
_client.SendData(WELCOME_MSG);
_salida = OK;
}
public boolean calibrar(Mat frame) {
Log.i(TAG, "Calibrando");
if (Calibracion.getInstance().calibrar(frame)) {
ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM,
50);
toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200); // ms
if (_salida == OK) {
_client.SendData("FIN calibrar\n . . . armando tablero!\n");
}
try {
_adquisicion = new Adquisicion();
_modelador = new Modelador();
_logica = new Logica();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
Log.i(TAG, "No calibrado");
ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50);
toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 700);
return false;
}
public void iniciarJuego() {
_estado = JUGANDO;
// beep
_detectorOclusion = new DetectorOclusion();
ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50);
toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200); // ms
if (_salida == OK) {
Mat tableroInicio = _logica.getTableroInicio();
_client.SendData("TableroINICIO!\n");
_client.SendData(" ".concat(tableroInicio.dump().concat("\n")));
}
}
public Mat processFrame(Mat inputFrame) {
Log.i(TAG, "Acondicionamiento");
Mat region = _adquisicion.processFrame(inputFrame);
Log.i(TAG, "TYPE=" + (inputFrame.type() == CvType.CV_8UC4));
Log.i(TAG, "CHANNEL=" + (inputFrame.channels() == 4));
switch (_estado) {
case ARMANDO_TABLERO:
Log.i(TAG, "Armando Tablero");
Mat nuevo = _modelador.getMatrizFichas(region);
if (_logica.validarTableroArmado(nuevo)) {
iniciarJuego();
}
break;
case JUGANDO:
Log.i(TAG, "Jugando");
if (_detectorOclusion.hayNuevoTableroValido(region)) {
Log.i(TAG, "Tablero Valido");
// llamar al modelador
Mat aux = _modelador.getMatrizFichas(region);
// Log.i(TAG, "MATRIZ=" + aux.dump());
// region = _modelador.dibujarEscaquesSobel(2);
if (_logica.validarNuevoTablero(aux)) {
if (_salida == OK) {
_client.SendData("Nuevo Tablero Valido = ["
+ String.valueOf(_cantJugada) + "]\n");
_cantJugada++;
_client.SendData(" ".concat(aux.dump().concat("\n")));
}
}
}
break;
}
if (_debug) {
Log.i(TAG, "DEBUG");
Mat tmp = Mat.zeros(inputFrame.size(), CvType.CV_8UC4);
Mat matTMP = tmp.submat(Calibracion.getRectROI());
region.copyTo(matTMP);
return tmp;
}
return inputFrame;
}
public void destroy() {
if (_client != null) {
_client.Stop();
}
}
}
package uy.edu.fing.chesstrack.modulovision.imgproc;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Vector;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.video.BackgroundSubtractorMOG;
import org.opencv.video.BackgroundSubtractorMOG2;
import org.opencv.imgproc.*;
import uy.edu.fing.chesstrack.communication.Client;
import android.graphics.SumPathEffect;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.util.Log;
public class BackgroundSupress implements ImgProcInterface {
private static final String TAG = "CHESSTRACK::BackgroundSupress";
private static int e = 0;
private final Mat fgMaskMOG;
private Mat fgMaskMOG2;
private final Mat morphKernel;
private final BackgroundSubtractorMOG pMOG;
private BackgroundSubtractorMOG2 pMOG2;
//private final List<MatOfPoint> contours;
private Client communicator;
private int estadoANTERIOR = 0;
private int estadoACTUAL = 0;
public BackgroundSupress() {
super();
morphKernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3,3));
fgMaskMOG = new Mat(4,1,CvType.CV_8UC1);
fgMaskMOG2 = new Mat(4,1,CvType.CV_8UC1);
pMOG = new BackgroundSubtractorMOG(); //MOG approach
pMOG2 = new BackgroundSubtractorMOG2(); //MOG approach
Log.i(TAG, "at background supress constructor");
//contours = new ArrayList<MatOfPoint>();
communicator = Client.getInstance();
}
@Override
public Mat procesarImagen(Mat inputFrame) {
Log.i(TAG, "BackgroundS ");
Mat copy = new Mat(inputFrame.size(),CvType.CV_8UC3);
inputFrame.convertTo(copy, CvType.CV_8UC3);
Imgproc.cvtColor(inputFrame, copy, Imgproc.COLOR_BGRA2BGR);
pMOG.apply(copy, fgMaskMOG);
pMOG2.apply(copy, fgMaskMOG2,0);
Log.i(TAG, "Apply pMOG");
Imgproc.erode(fgMaskMOG2, fgMaskMOG2, morphKernel);
Log.i(TAG, "Apply erode");
Imgproc.threshold(fgMaskMOG2, fgMaskMOG2, 200, 255, Imgproc.THRESH_BINARY);
Log.i(TAG, "Apply threshold");
//Imgproc.dilate(fgMaskMOG2, fgMaskMOG2, morphKernel);
//Log.i(TAG, "Apply dilate");
Scalar suma = Core.sumElems(fgMaskMOG2);
Log.i(TAG, "SUMA = " + suma);
/*double maxArea = 0;
MatOfPoint largestContour = null;
Imgproc.findContours(fgMaskMOG2, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_TC89_L1);
for (MatOfPoint contour : contours) {
double area = Imgproc.contourArea(contour);
if (area > maxArea) {
maxArea = area;
largestContour = contour;
}
}
Log.i(TAG, "ESTABLE !!!" + maxArea);
if ((largestContour != null) && (maxArea > 10000)){
Log.i(TAG, "MANO !!!" + maxArea);
Rect boundingRect = Imgproc.boundingRect(largestContour);
ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50);
toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200); // 200 is duration in ms
}*/
if (suma.val[0] > 100000){
estadoANTERIOR = estadoACTUAL;
estadoACTUAL = 1;
Log.i(TAG, "MANO !!!");
communicator.SendData("1\n");
Core.putText(fgMaskMOG2, "MANO !!!", new Point(50, 50),Core.FONT_HERSHEY_SIMPLEX, 0.8 , new Scalar(255,255,0));
// ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50);
// toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 200); // 200 is duration in ms
} else {
estadoANTERIOR = estadoACTUAL;
if (estadoANTERIOR == 1){
// estado transicion
estadoACTUAL = 3;
}
if (estadoANTERIOR == 3){
// estado estable
estadoACTUAL = 2;
pMOG2 = new BackgroundSubtractorMOG2(); //MOG2 approach
}
Log.i(TAG, "ESTABLE !!!");
communicator.SendData("0\n");
Core.putText(fgMaskMOG2, "ESTABLE !!!", new Point(50, 50),Core.FONT_HERSHEY_SIMPLEX, 0.5 , new Scalar(255,255,0));
}
/*Imgproc.findContours(fgMaskMOG2, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_NONE);
for(int idx = 0; idx < contours.size(); idx++)
{
double area = Imgproc.contourArea(contours.get(idx));
Log.i(TAG, "CONTOUR = AREA: " + area);
if ((area > 15000) && (area < 70000)){
Log.i(TAG, "DRAW !!! : " + area);
Scalar color = new Scalar(255,127,127);
Rect r = Imgproc.boundingRect(contours.get(idx));
Log.i(TAG, "3 at backgroundS "+(fgMaskMOG2.type() == CvType.CV_8UC1));
Core.rectangle(fgMaskMOG2, r.tl(), r.br(), color, 2, 8, 0);
//Imgproc.drawContours(fgMaskMOG2, contours, idx, color);
}
}
contours.clear();*/
Log.i(TAG, "END Background Sss");
return fgMaskMOG2;
}
}
......@@ -3,17 +3,32 @@ package uy.edu.fing.chesstrack.modulovision.imgproc;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import android.util.Log;
public class EcualizarImagen implements ImgProcInterface {
private static final String TAG = "CHESSTRACK::Ecualizar";
@Override
public Mat procesarImagen(Mat inputFrame) {
// TODO Auto-generated method stub
//cvEqualizeHist(src,dest)
Mat viewGray = new Mat();
Imgproc.cvtColor(inputFrame, viewGray, Imgproc.COLOR_BGR2GRAY);
Imgproc.equalizeHist(viewGray,viewGray);
//Imgproc.equalizeHist(inputFrame,inputFrame);
return viewGray;
}
//List<Mat> channels = new ArrayList<Mat>();
Mat img_hist_equalized = new Mat();
Log.i(TAG, "processing Frame - INI");
Imgproc.cvtColor(inputFrame, img_hist_equalized, Imgproc.COLOR_BGR2GRAY);
Imgproc.equalizeHist(img_hist_equalized, img_hist_equalized);
Imgproc.cvtColor(img_hist_equalized, inputFrame, Imgproc.COLOR_GRAY2BGR);
/*// ecualizar en cada canal
Core.split(inputFrame, channels); // split the image into channels
//Imgproc.equalizeHist(channels.get(0), channels.get(0));
Imgproc.equalizeHist(channels.get(1), channels.get(1));
//Imgproc.equalizeHist(channels.get(2), channels.get(2));
Core.merge(channels, inputFrame);
*/
Log.i(TAG, "processing Frame - FIN");
return img_hist_equalized;
}
}
......@@ -14,104 +14,105 @@ import android.util.Log;
public class Homografia implements ImgProcInterface {
private static final String TAG = "CHESSTRACK::Homografia";
private final Mat matrizTransformada;
private final Rect rectPOI;
private int media;
private int offset;
private final Mat _matrizTransformada;
private final Rect _rectROI;
private int _media;
private int _offset;
public Homografia() throws Exception {
super();
MatOfPoint2f vertices = Calibracion.getInstance().getVertices();
if (vertices != null){
Mat src = new Mat(4,1,CvType.CV_32FC2);
Mat dst = new Mat(4,1,CvType.CV_32FC2);
Point p1, p2, p3, p4;
Point[] ret = getBestPoints(vertices, Calibracion.getInstance().getImagenCalibrada().size());
Log.i(TAG, "coso= " + ret);
Point[] ret = getBestPoints(vertices, Calibracion.getInstance().get_sizeFrame());
Log.i(TAG, "Best Points= " + ret.toString());
p1 = ret[0];
p2 = ret[1];
p3 = ret[2];
p4 = ret[3];
double d17 = Math.sqrt(Math.pow((p1.x- p2.x),2) + Math.pow((p1.y- p2.y),2));
double d749 = Math.sqrt(Math.pow((p2.x- p3.x),2) + Math.pow((p2.y- p3.y),2));
double d143 = Math.sqrt(Math.pow((p3.x- p4.x),2) + Math.pow((p3.y- p4.y),2));
double d4349 = Math.sqrt(Math.pow((p4.x- p1.x),2) + Math.pow((p4.y- p1.y),2));
media = (int) Math.floor( Math.round((d17+d749+d143+d4349)/4));
offset = 2*(media/6);
src.put(0,0 ,(int)p1.x,(int)p1.y, (int)p2.x,(int)p2.y, (int)p3.x,(int)p3.y, (int)p4.x,(int)p4.y);
dst.put(0,0, offset,offset ,offset+media,offset , offset+media,offset+media, offset,offset+media );
// EL offset es casi el tamaño de una celda
rectPOI = new Rect(new Point(0,0), new Point(2*offset+media,2*offset+media) );
Calibracion.getInstance().setRectPOI(rectPOI);
matrizTransformada = Imgproc.getPerspectiveTransform(src,dst);
}else{
// se obtienen las distancias de cada una de las aristas que determinan los vertices
// internos mas externos y se determina el promedio de esa medida
double d12 = Math.sqrt(Math.pow((p1.x- p2.x),2) + Math.pow((p1.y- p2.y),2));
double d23 = Math.sqrt(Math.pow((p2.x- p3.x),2) + Math.pow((p2.y- p3.y),2));
double d34 = Math.sqrt(Math.pow((p3.x- p4.x),2) + Math.pow((p3.y- p4.y),2));
double d14 = Math.sqrt(Math.pow((p4.x- p1.x),2) + Math.pow((p4.y- p1.y),2));
_media = (int) Math.floor( Math.round((d12+d23+d34+d14)/4));
// El offset es el tamaño de dos celdas (para abarcar el primer casillero y dejar un borde al tablero
_offset = 2*(_media/6);
Log.i(TAG, "media= " + _media);
Log.i(TAG, "offset= " + _offset);
src.put(0,0, (int)p1.x,(int)p1.y, (int)p2.x,(int)p2.y, (int)p3.x,(int)p3.y, (int)p4.x,(int)p4.y);
dst.put(0,0, _offset,_offset, _offset+_media,_offset, _offset+_media,_offset+_media, _offset,_offset+_media );
_rectROI = new Rect(new Point(0,0), new Point(2*_offset+_media,2*_offset+_media));
Calibracion.getInstance();
Calibracion.setRectROI(_rectROI);
Log.i(TAG, "rectROI size= " + _rectROI.size());
_matrizTransformada = Imgproc.getPerspectiveTransform(src,dst);
} else {
throw new Exception(TAG + "No se han calculado los vertices");
}
}
/**
* Hace homografia y recorta la imagen
*/
@Override
public Mat procesarImagen(Mat inputFrame) {
Log.i(TAG, "processing Frame - INI");
double x = inputFrame.size().width;
double y = inputFrame.size().height;
if (x < _rectROI.size().width){
x = _rectROI.size().width;
}
if (y < _rectROI.size().height){
y = _rectROI.size().height;
}
Mat aux = new Mat();
Log.i(TAG, "before");
Imgproc.warpPerspective(inputFrame,inputFrame, matrizTransformada, inputFrame.size());
Mat subMat = inputFrame.submat(rectPOI);
Mat tmp = Mat.zeros(inputFrame.size(), CvType.CV_8UC4);
Mat matTMP = tmp.submat(rectPOI);
subMat.copyTo(matTMP);
Log.i(TAG, "after");
// hace la homografia con la matriz calculada en un ppio
Imgproc.warpPerspective(inputFrame,aux, _matrizTransformada, new Size(x,y));
Mat tmp = Mat.zeros(_rectROI.size(), CvType.CV_8UC4);
(aux.submat(_rectROI)).copyTo(tmp);
Log.i(TAG, "processing Frame - FIN");
return tmp;
}
private Point[] getBestPoints(MatOfPoint2f vertices, Size tamanio){
double d, best_dist;
Point[] ret = new Point[4];
Point[] vect = new Point[4];
double d, dx ,dy;
double betst_dist = Double.MAX_VALUE;
Point aux = new Point(0,0);
for(Point pt : vertices.toList()){
d = Math.sqrt(Math.pow((pt.x- aux.x),2) + Math.pow((pt.y- aux.y),2));
if (d < betst_dist){
betst_dist = d;
ret[0] = pt;
}
}
betst_dist = Double.MAX_VALUE;
aux = new Point(tamanio.width,0);
for(Point pt : vertices.toList()){
d = Math.sqrt(Math.pow((pt.x- aux.x),2) + Math.pow((pt.y- aux.y),2));
if (d < betst_dist){
betst_dist = d;
ret[1] = pt;
}
}
vect[0] = new Point(0,0);
vect[1] = new Point(tamanio.width,0);
vect[2] = new Point(tamanio.width,tamanio.height);
vect[3] = new Point(0,tamanio.height);
betst_dist = Double.MAX_VALUE;
aux = new Point(tamanio.width,tamanio.height);
for(Point pt : vertices.toList()){
d = Math.sqrt(Math.pow((pt.x- aux.x),2) + Math.pow((pt.y- aux.y),2));
if (d < betst_dist){
betst_dist = d;
ret[2] = pt;
}
for (int i = 0; i < 4; i++){
Point aux = vect[i];
best_dist = Double.MAX_VALUE;
for(Point pt : vertices.toList()){
d = Math.sqrt(Math.pow((pt.x- aux.x),2) + Math.pow((pt.y- aux.y),2));
if (d < best_dist){
best_dist = d;
ret[i] = pt;
}
}
}
betst_dist = Double.MAX_VALUE;
aux = new Point(0,tamanio.height);
for(Point pt : vertices.toList()){
d = Math.sqrt(Math.pow((pt.x- aux.x),2) + Math.pow((pt.y- aux.y),2));
if (d < betst_dist){
betst_dist = d;
ret[3] = pt;
}
}
return ret;
}
}
package uy.edu.fing.chesstrack.modulovision.imgproc;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import org.opencv.video.BackgroundSubtractorMOG2;
public class SustraccionDeFondo implements ImgProcInterface {
private Mat fMaskMOG = null;
private final BackgroundSubtractorMOG2 pMOG;
private static final String TAG = "CHESSTRACK::SustraccionDeFondo";
public SustraccionDeFondo(){
pMOG = new BackgroundSubtractorMOG2();
//fMaskMOG = new Mat();
}
@Override
public Mat procesarImagen(Mat inputFrame) {
Imgproc.cvtColor(inputFrame, inputFrame, Imgproc.COLOR_RGBA2RGB);
fMaskMOG = new Mat(inputFrame.size(),inputFrame.channels());
pMOG.apply(inputFrame, fMaskMOG);
//Mat frame = inputFrame.submat(Calibracion.getInstance().getRectPOI());
//fMaskMOG = new Mat(frame.size(),frame.channels());
//pMOG.apply(frame, fMaskMOG);
//Imgproc.resize(inputFrame, frame, frame.size());
//Log.i(TAG, "Size frame= " + frame.size());
//Log.i(TAG, "Size fMaskMOG= " + fMaskMOG.size());
//Rect aux = Calibracion.getInstance().getRectPOI();
//frame.copyTo(frame,fMaskMOG);
//Mat subMat = inputFrame.submat(0,frame.rows(),0,frame.cols());
//frame.copyTo(subMat);
//Mat frame = new Mat();
//inputFrame.copyTo(frame,fMaskMOG);
return fMaskMOG;
}
}
......@@ -3,3 +3,6 @@ project( SubsBackground )
find_package( OpenCV REQUIRED )
add_executable( SubsBackground SubsBackground.cpp )
target_link_libraries( SubsBackground ${OpenCV_LIBS} )
project( Corners )
add_executable( Corners Corners.cpp )
target_link_libraries( Corners ${OpenCV_LIBS} )
#include <string>
#include <iostream>
#include <vector>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
//----------------------------------------------------------
// MAIN
//----------------------------------------------------------
int main(int argc, char* argv[])
{
// src image
Mat src;
// dst image
Mat dst;
// Image loading
namedWindow("result");
namedWindow("src");
src=imread("image.png",0);
cv::cvtColor(src,dst,cv::COLOR_GRAY2BGR);
Mat corners;
cv::goodFeaturesToTrack(src,corners,100,0.01,20.0);
for(int i=0;i<corners.rows;++i)
{
circle(dst,cv::Point(corners.at<float>(i,0),corners.at<float>(i,1)),3,Scalar(255,0,0),-1,CV_AA);
}
imshow("src",src);
imshow("result",dst);
//----------------------------------------------------------
// Wait key press
//----------------------------------------------------------
while (waitKey(0) != 'q');
destroyAllWindows();
return 0;
}
......@@ -45,6 +45,7 @@ h5 {
}
p {
margin-bottom: 20px;
font-size: 15px;
}
.lead {
font-size: 14px;
......
This diff is collapsed.
<!DOCTYPE html>
<html lang="en">
<head>
<title>ChessTrack.::.Introducción</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Your description">
<meta name="keywords" content="Your keywords">
<meta name="author" content="Your name">
<link rel="icon" href="img/favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="css/bootstrap.css" type="text/css" media="screen">
<link rel="stylesheet" href="css/responsive.css" type="text/css" media="screen">
<link rel="stylesheet" href="css/camera.css" type="text/css" media="screen">
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen">
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600,700' rel='stylesheet' type='text/css'>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.easing.1.3.js"></script>
<script type="text/javascript" src="js/camera.js"></script>
<script src="js/jquery.ui.totop.js" type="text/javascript"></script>
</head>
<body>
<!--==============================header=================================-->
<header class="p0">
<div class="container">
<div class="row">
<div class="span12">
<div class="header-block clearfix">
<div class="clearfix header-block-pad">
<h1 class="brand"><a href="index.html"><img src="img/logo.png" alt=""></a><span>Seguimiento de una Partida de Ajedrez.</span></h1>
<span class="contacts">Integrantes:<br>
<span>&nbsp;&nbsp;&nbsp;Aylen Ricca (<a href="mailto:aricca@fing.edu.uy">aricca@fing.edu.uy</a>)<br>&nbsp;&nbsp;&nbsp;Nicolás Furquez (<a href="mailto:nfurquez@fing.edu.uy">nfurquez@fing.edu.uy</a>)</span>
<br>Tutor:<br>
<span>&nbsp;&nbsp;&nbsp;Álvaro Gómez (<a href="mailto:agomez@fing.edu.uy">agomez@fing.edu.uy</a>)</span>
</span>
<span class="contacts">
<img src="img/chess0.png" alt="">
</span>
</div>
<div class="navbar navbar_ clearfix">
<div class="navbar-inner navbar-inner_">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse_">MENU</a>
<div class="nav-collapse nav-collapse_ collapse">
<ul class="nav sf-menu">
<li class="active li-first"><a href="index.html"><em class="hidden-phone"></em><span class="visible-phone">Home</span></a></li>
<li class="sub-menu"><a href="#">Introducción</a>
<ul>
<li><a href="descripcion_del_proyecto.html">Descripción del Proyecto</a></li>
<li class="sub-menu"><a href="#">Documentos</a>
<ul>
<li><a href="documentos/presentacion_inicial.pdf" target="_blank">Presentación Inicial</a></li>
<li><a href="documentos/plan_de_trabajo.pdf">Plan de Trabajo</a></li>
<li><a href="documentos/presentacion_final.pdf">Presentación Final</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="desarrollo.html">Desarrollo</a></li>
<li><a href="trabajo_a_futuro.html">Trabajo a Futuro</a></li>
<li><a href="links_de_interes.html">Links de Interés</a></li>
<li><a href="galeria_de_imagenes.html">Galería de Imágenes</a></li>
<li><a href="videos.html">Videos</a></li>
</ul>
</div>
<ul class="social-icons">
<li><a href="http://www.fing.edu.uy/"><img src="img/icon-1.png" alt=""></a></li>
<li><a href="http://www.universidad.edu.uy/"><img src="img/icon-2.png" alt=""></a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</header>
<!--==============================content=================================-->
<section id="content">
<div class="sub-content">
<div class="container">
<div class="row">
<div class="span6 float2">
<br><br><br><br><br>
<p>Como antecedentes se cuenta con un proyecto de la asignatura llevado a cabo en 2013, 8x8CAM, el cual es similar en características pero desarrollado para PC y sólo se tomaban fotogramas del tablero antes y después del movimiento, en nuestro caso el procesamiento es en tiempo real y es de sumo interés poder identificar cuándo obtener frames con tableros válidos.</p>
<p>El tablero utilizado será uno profesional como los de la figura, proporcionado por el tutor; se utilizará un ambiente donde la iluminación será controlada y la partida será “lenta”, con esto se quiere decir que se dará tiempo al dispositivo a procesar la partida entre movimiento y movimiento.</p>
<figure>
<img src="galeria/img_desc_03.png" class="img-radius" alt="Tablero Profesional" style="width: 250px">
&nbsp;&nbsp;
<img src="galeria/img_desc_04.png" class="img-radius" alt="Tablero Profesional" style="width: 250px">
</figure>
<p>Como objetivo opcional, se plantea la posibilidad de transcribir la partida a voz para jugadores no videntes.</p>
<p>Dado que una partida normal de ajedrez es muy rica en movimientos, en un principio se plantea la detección de una partida con movimientos básicos, en la segunda iteración se incluirá la detección de jake y jake mate, valiéndose de las <a href="http://es.wikipedia.org/wiki/Reglamento_del_ajedrez">reglas</a> oficiales de ajedrez, si el tiempo lo permite se tratará de detectar enroques, coronaciones (promociones) y captura al paso, igualmente se tendrá en cuenta en el diseño de la arquitectura estos casos especiales para una futura extensión.</p>
<p>Para procesar las capturas de una forma más eficiente se usará la biblioteca <a href="http://docs.opencv.org/doc/tutorials/introduction/android_binary_package/O4A_SDK.html">OpenCV4Android</a> dado que cuenta con una gran cantidad de utilitarios para el procesamiento de imágenes.</p>
</div>
<div class="span6 float">
<h4>Descripción del Proyecto.</h4>
<p><strong class="clr">En los siguientes párrafos se describen los lineamientos del proyecto.</strong><br>
El trabajo que se aborda es el procesamiento en tiempo real de una partida lenta de ajedrez desde un dipositivo móvil mediante tratamiento de imágenes. A su vez, contar con la persistencia y/o transmisión de la partida en <a href="http://es.wikipedia.org/wiki/Notaci%C3%B3n_algebraica">notación algebraica</a>.</p>
<figure>
<a href="https://www.youtube.com/v/GdQmgzBK0Jo"><img src="galeria/img_desc_01.png" class="img-radius" alt="Reproducción de partida" style="width: 300px"></a>
&nbsp;&nbsp;&nbsp;&nbsp;
<img src="galeria/img_desc_02.png" class="img-radius" alt="Notación algebraica" style="height: 300px">
</figure>
<p>Las restricciones que se plantean para esta realidad son la utilización de un tablero profesional, su ubicación en una posicion fija, iluminación controlada y el dispositivo móvil colocado de tal manera que pueda captar con su cámara la totalidad del tablero.</p>
<p>EL proyecto se en marca dentro del proyecto final la asignatura <a href="https://eva.fing.edu.uy/course/view.php?id=520">Tratamiendo de Imágenes por Computador</a> del <a href="http://iie.fing.edu.uy/">Instituto de Ingeniería Eléctrica</a> de la Facultad de Ingeniería de la Universidad de la República. El mismo, como se mencionó anteriormente consiste en reconocer el movimiento de las piezas dentro de una partida de ajedrez. El problema es interesante desde el punto de vista del tratamiento de imágenes, dado que posee una complejidad rica en problemas comunes en el proceso de racionalizar una imagen, desde detectar dónde se ubica cada ficha en todo momento y reconocer su recorrido, hasta saber cuando no se debe de procesar una imagen ya que el jugador está moviendo las piezas en ese momento.</p>
<p>El problema planteado se presenta en el marco de una partida de ajedrez clásica, en donde interesa transcribir a notación algebraica la partida, en tiempo real, para ser enviada a un servidor o un jugador remoto. Como hoy en día es muy accesible tener un celular con la potencia para procesar imágenes, el proyecto se llava a cabo con la tecnología <a href="http://developer.android.com/index.html">Android</a>.</p>
</div>
</div>
</div>
</div>
</section>
<!--==============================footer=================================-->
<footer>
<div class="container">
<div class="row">
<div class="span4 float2">
Proyecto de fin de curso 2014 de Tratamiento de Imágenes por Computadora dictado en la Facultad de Ingeniería de la Universidad de la República, Uruguay
<br>Sitio web del curso: <a href="https://eva.fing.edu.uy/course/view.php?id=520">Tratamiento de Imágenes por Computadora</a>
</div>
<div class="span8 float">
<ul class="footer-menu">
<li><a href="descripcion_del_proyecto.html">Descripción del Proyecto</a>|</li>
<li><a href="desarrollo.html">Desarrollo</a>|</li>
<li><a href="trabajo_a_futuro.html">Trabajo a Futuro</a>|</li>
<li><a href="links_de_interes.html">Links de Interés</a></li>
<li><a href="galeria_de_imagenes.html">Galería de Imágenes</a></li>
<li><a href="videos.html">Videos</a></li>
</ul>
Stylish 2014 | <a href="mailto:aricca8@gmail.com">@yle</a>
</div>
</div>
</div>
</footer>
<script type="text/javascript" src="js/bootstrap.js"></script>
</body>
</html>
\ No newline at end of file