diff --git a/.gitignore b/.gitignore index 93b880f8b1c3cb89c8dc79fa8311071fb84e81ea..383a749b005810bbed5a138ec10c3e95c237db05 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,8 @@ *~ # Directories # -#ProyectoAndroid/ChessTrack/bin +ProyectoAndroid/ChessTrack/bin/* +ProyectoAndroid/ChessTrack/gen/* #java specific *.class diff --git a/ProyectoAndroid/ChessTrack/AndroidManifest.xml b/ProyectoAndroid/ChessTrack/AndroidManifest.xml index 996edd019bf650805d4125459a26a78f71c9f254..634c447944e1dd3b5cf8d3de60f0387c4f3200ea 100644 --- a/ProyectoAndroid/ChessTrack/AndroidManifest.xml +++ b/ProyectoAndroid/ChessTrack/AndroidManifest.xml @@ -37,9 +37,9 @@ android:minSdkVersion="9" android:targetSdkVersion="10" /> - <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> + <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"/> diff --git a/ProyectoAndroid/ChessTrack/res/layout/chess_track_layout b/ProyectoAndroid/ChessTrack/res/layout/chess_track_layout.xml similarity index 64% rename from ProyectoAndroid/ChessTrack/res/layout/chess_track_layout rename to ProyectoAndroid/ChessTrack/res/layout/chess_track_layout.xml index ff76e96866c4108319f0ec4b9bdb575d19ce754e..f99d5f01d5796b618a783703a9d6eaa55f9ecd18 100644 --- a/ProyectoAndroid/ChessTrack/res/layout/chess_track_layout +++ b/ProyectoAndroid/ChessTrack/res/layout/chess_track_layout.xml @@ -1,15 +1,9 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:opencv="http://schemas.android.com/apk/res-auto" - android:layout_width="match_parent" - android:layout_height="match_parent" > - - <Button - android:id="@+id/btn_calibrar" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="calibrar" /> - + android:layout_width="wrap_content" + android:layout_height="wrap_content" + > <org.opencv.android.JavaCameraView android:layout_width="fill_parent" diff --git a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/ChessTrackActivity.java b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/ChessTrackActivity.java index 953e9014b7e0f8c196f64a0b1917c98179a3b29c..38f73e3d94b87dffcf56aef10819a0799a6ae8b6 100644 --- a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/ChessTrackActivity.java +++ b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/ChessTrackActivity.java @@ -7,8 +7,8 @@ import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; import org.opencv.core.Mat; - -import uy.edu.chesstrack.communication.Client; +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 android.app.Activity; @@ -19,9 +19,9 @@ import android.media.ToneGenerator; import android.os.Bundle; import android.text.Editable; import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; import android.view.SurfaceView; -import android.view.View; -import android.view.View.OnClickListener; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; @@ -44,7 +44,7 @@ public class ChessTrackActivity extends Activity implements CvCameraViewListener private Calibracion calibrar; private Button btnCalibrar; private Client ClientCommunication; - + private MenuItem mItemCalibrar; //TODO es chancho pero ver luego private Mat frame; private boolean isUsed; @@ -84,10 +84,11 @@ public class ChessTrackActivity extends Activity implements CvCameraViewListener mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.chess_track_layout); mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE); mOpenCvCameraView.setCvCameraViewListener(this); + Modelador.getInstance(); try { isUsed = false; isCalibrada =false; - addListenerOnButton(); + } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -158,35 +159,39 @@ public class ChessTrackActivity extends Activity implements CvCameraViewListener alert.show(); } - public void addListenerOnButton() { - - btnCalibrar = (Button) findViewById(R.id.btn_calibrar); - - btnCalibrar.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View arg0) { - isUsed = true; - if(frame!=null){ - if (Calibracion.getInstance().calibrar(frame)){ - isCalibrada = true; - 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(); - } - }else{ - ToneGenerator toneG = new ToneGenerator(AudioManager.STREAM_ALARM, 50); - toneG.startTone(ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD, 700); // 200 is duration in ms + @Override + public boolean onCreateOptionsMenu(Menu menu) { + Log.i(TAG, "called onCreateOptionsMenu"); + mItemCalibrar = menu.add("Show/hide tile numbers"); + + 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 } - isUsed = false; } - - }); + isUsed = false; + } + return true; } @@ -230,7 +235,11 @@ public class ChessTrackActivity extends Activity implements CvCameraViewListener if(isCalibrada){ Log.i(TAG, "calibrada"); - return adq.processFrame(inputFrame); + + inputFrame = adq.processFrame(inputFrame); + //Modelador.getInstance().dividirTablero(inputFrame); + //return Modelador.getInstance().dibujarEscaque(2, 3); + return inputFrame; } return inputFrame; diff --git a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/communication/Client.java b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/communication/Client.java new file mode 100644 index 0000000000000000000000000000000000000000..4645609897eaa13110c1949ad4a0e0828bed87c4 --- /dev/null +++ b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/communication/Client.java @@ -0,0 +1,84 @@ +package uy.edu.fing.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 { + Log.i(TAG, "Server on " + this._serverIp + ":" + _serverPort); + InetAddress serverAddr = InetAddress.getByName(this._serverIp); + serverSocket = new Socket(serverAddr, _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(); + } + } +} diff --git a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulomodelador/Modelador.java b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulomodelador/Modelador.java new file mode 100644 index 0000000000000000000000000000000000000000..567328c35d92a7f96d8a0bd4e298c0027b5157f7 --- /dev/null +++ b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulomodelador/Modelador.java @@ -0,0 +1,63 @@ +package uy.edu.fing.chesstrack.modulomodelador; + +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.Point; +import org.opencv.core.Rect; + +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; + // se cuentan de arrib a abajo y de izquierda a derecha + private final Mat[][] escaques; + private static Modelador instance; + + + private Modelador(){ + tablero = new int[CANT_FILAS][CANT_FILAS]; + 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(); + // obtengo cuanto mide en ancho y largo un escaque + int largoEscaque = (int) Math.floor(largo /(CANT_FILAS+1) );//+1 porque se toma un escaque mas de borde + int anchoEscaque = (int) Math.floor(ancho /(CANT_FILAS+1) ); + Log.i(TAG, "largoEscaque= " + largoEscaque); + Log.i(TAG, "anchoEscaque= " + anchoEscaque); + for (int i = 0; i < CANT_FILAS; i++){ + for (int j = 0; j < CANT_FILAS; j++){ + int rowStart=(int)Math.floor(largoEscaque/2)+ i*largoEscaque +2; + int rowEnd = (int)Math.floor(largoEscaque/2)+i*largoEscaque + largoEscaque -2; + int colStart = (int)Math.floor(anchoEscaque/2)+j*anchoEscaque + 2; + int colEnd = (int)Math.floor(anchoEscaque/2)+j*anchoEscaque + anchoEscaque - 2;; + escaques[i][j]= inputFrame.submat(rowStart, rowEnd, colStart, colEnd); + } + } + } + + public Mat dibujarEscaque(int i, int j){ + Mat tmp = Mat.zeros(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); + return tmp; + } + +} diff --git a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/Adquisicion.java b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/Adquisicion.java index 2a7b0e810772e55d1834ddebc4047bb0ea8be0fa..fb3abdc1a107b886b6acc3fc3ed1e810483a755c 100644 --- a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/Adquisicion.java +++ b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/Adquisicion.java @@ -7,9 +7,9 @@ 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 uy.edu.fing.chesstrack.modulovision.imgproc.SustraccionDeFondo; import android.util.Log; @@ -25,9 +25,11 @@ public class Adquisicion { Log.i(TAG, "Cargado...."); listProc = new ArrayList<ImgProcInterface>(); - listProc.add( new Homografia()); + //listProc.add( new Homografia()); //listProc.add( new EcualizarImagen()); - listProc.add( new SustraccionDeFondo()); + //listProc.add( new SustraccionDeFondo()); + listProc.add( new BackgroundSupress()); + } /** diff --git a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/imgproc/BackgroundSupress.java b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/imgproc/BackgroundSupress.java index 419eb090b0a71b8065042795516d07463e99b613..697c72730d70804dde9c720ea56bbf23efec8ba2 100644 --- a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/imgproc/BackgroundSupress.java +++ b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/imgproc/BackgroundSupress.java @@ -17,7 +17,7 @@ import org.opencv.video.BackgroundSubtractorMOG; import org.opencv.video.BackgroundSubtractorMOG2; import org.opencv.imgproc.*; -import uy.edu.chesstrack.communication.Client; +import uy.edu.fing.chesstrack.communication.Client; import android.graphics.SumPathEffect; import android.media.AudioManager; import android.media.ToneGenerator; diff --git a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/imgproc/Homografia.java b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/imgproc/Homografia.java index 8b4b5b2b2b6021949209e5ebf2783941c3cbf26f..31154b7d6f18458f01e5059d9d2be2b2c2c4e63e 100644 --- a/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/imgproc/Homografia.java +++ b/ProyectoAndroid/ChessTrack/src/uy/edu/fing/chesstrack/modulovision/imgproc/Homografia.java @@ -5,17 +5,18 @@ import org.opencv.core.Mat; import org.opencv.core.MatOfPoint2f; import org.opencv.core.Point; import org.opencv.core.Rect; +import org.opencv.core.Size; import org.opencv.imgproc.Imgproc; import uy.edu.fing.chesstrack.modulovision.Calibracion; -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; public Homografia() throws Exception { super(); MatOfPoint2f vertices = Calibracion.getInstance().getVertices(); @@ -32,15 +33,33 @@ public class Homografia implements ImgProcInterface { double d143 = Math.sqrt(Math.pow((p1.x- p3.x),2) + Math.pow((p1.y- p3.y),2)); double d4349 = Math.sqrt(Math.pow((p3.x- p4.x),2) + Math.pow((p3.y- p4.y),2)); - int media = (int) Math.floor( Math.round((d17+d749+d143+d4349)/4)); - int offset = 2*(media/7); + media = (int) Math.floor( Math.round((d17+d749+d143+d4349)/4)); + offset = 2*(media/7); + // offset = (media/7); + // Point p1, p2, p3, p4; + // Point[] ret = getBestPoints(vertices, Calibracion.getInstance().getImagenCalibrada().size()); + // Log.i(TAG, "coso= " + ret); + // p1 = ret[0]; + // p2 = ret[1]; + // p3 = ret[2]; + // p4 = ret[3]; + // + // double corner_width = Math.abs(Math.sqrt(Math.pow((p1.x- p2.x),2) + Math.pow((p1.y- p2.y),2))/7); + // double corner_height = corner_width; + // + // double real_left_x = 0 + corner_width; + // double real_right_x = 0 + 9 * corner_width; + // double real_top_y = 0 + corner_height; + // double real_bottom_y = 0 + 9 * corner_height; 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, real_left_x ,real_top_y ,real_right_x ,real_top_y, real_right_x,real_bottom_y, real_left_x,real_bottom_y ); dst.put(0,0, offset,offset ,offset+media,offset , offset,offset+media , offset+media,offset+media ); - Log.i(TAG, "offset= " + offset); - Log.i(TAG, "media = " + media); + // Log.i(TAG, "corner_width= " + corner_width); + // Log.i(TAG, "corner_height = " + corner_height); // 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)); + //rectPOI = new Rect(new Point(0,0), new Point(9*corner_width,9*corner_height) ); + 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{ @@ -53,14 +72,74 @@ public class Homografia implements ImgProcInterface { @Override public Mat procesarImagen(Mat inputFrame) { - Imgproc.warpPerspective(inputFrame,inputFrame, matrizTransformada, inputFrame.size()); + Imgproc.warpPerspective(inputFrame,inputFrame, matrizTransformada, inputFrame.size(),(Imgproc.INTER_LINEAR | Imgproc.CV_WARP_FILL_OUTLIERS)); Mat subMat = inputFrame.submat(rectPOI); Mat tmp = Mat.zeros(inputFrame.size(), CvType.CV_8UC4); Mat matTMP = tmp.submat(rectPOI); subMat.copyTo(matTMP); return tmp; + //Core.circle(inputFrame, new Point(offset,offset), offset, new Scalar(0,0 , 255, 255)); + //Core.circle(inputFrame, new Point(offset,offset), 5, new Scalar(0,255, 0, 255)); + // return inputFrame; } + private Point[] getBestPoints(MatOfPoint2f vertices, Size tamanio){ + Point[] ret = new Point[4]; + + double d, dx ,dy; + double betst_dist = Double.MAX_VALUE; + Point aux = new Point(0,0); + for(Point pt : vertices.toList()){ + // dx = pt.x-aux.x; + // dy= pt.y -aux.y; + // d = dx*dx + dy*dy; + 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()){ + // dx = pt.x - aux.x; + // dy= pt.y -aux.y; + // d = dx*dx + dy*dy; + 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; + } + } + + betst_dist = Double.MAX_VALUE; + aux = new Point(tamanio.width,tamanio.height); + for(Point pt : vertices.toList()){ + // dx = pt.x-aux.x; + // dy= pt.y -aux.y; + // d = dx*dx + dy*dy; + 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; + } + } + + betst_dist = Double.MAX_VALUE; + aux = new Point(0,tamanio.height); + for(Point pt : vertices.toList()){ + // dx = pt.x-aux.x; + // dy= pt.y -aux.y; + // d = dx*dx + dy*dy; + 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; + } }