/*
* Artcodes recognises a different marker scheme that allows the
* creation of aesthetically pleasing, even beautiful, codes.
* Copyright (C) 2013-2016 The University of Nottingham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package uk.ac.horizon.artcodes.detect.handler;
import android.graphics.Bitmap;
import android.util.Log;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Rect;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import java.util.ArrayList;
import java.util.Collection;
import uk.ac.horizon.artcodes.detect.marker.Marker;
import uk.ac.horizon.artcodes.drawer.MarkerDrawer;
import uk.ac.horizon.artcodes.model.Action;
import uk.ac.horizon.artcodes.model.Experience;
import uk.ac.horizon.artcodes.model.MarkerImage;
public class MarkerActionDetectionHandler extends MarkerCodeDetectionHandler
{
protected static final int REQUIRED = 5;
protected static final int MAX = REQUIRED;
// Keep displayed for 10s
private static final int REMAIN = 10000;
private final ActionDetectionHandler markerActionHandler;
private final Experience experience;
private final MarkerDrawer markerDrawer;
private Action currentAction;
private long lastSeen;
public MarkerActionDetectionHandler(ActionDetectionHandler markerActionHandler, Experience experience, MarkerDrawer markerDrawer)
{
super(experience, null);
this.markerActionHandler = markerActionHandler;
this.experience = experience;
this.markerDrawer = markerDrawer;
}
@Override
public void onMarkersDetected(Collection<Marker> markers, ArrayList<MatOfPoint> contours, Mat hierarchy, Size sourceImageSize)
{
countMarkers(markers);
long now = System.currentTimeMillis();
int best = 0;
Action selected = null;
for (Action action : this.experience.getActions())
{
if (action.getMatch() == Action.Match.any)
{
for (String code : action.getCodes())
{
int count = markerCounts.count(code);
if (count > best)
{
selected = action;
best = count;
}
}
}
else if (action.getMatch() == Action.Match.all)
{
int min = MAX;
int total = 0;
for (String code : action.getCodes())
{
int count = markerCounts.count(code);
min = Math.min(min, count);
total += (count * 2);
}
if (min > REQUIRED && total > best)
{
best = total;
selected = action;
}
}
}
if (best < REQUIRED)
{
if (currentAction != null)
{
if(now - lastSeen > REMAIN)
{
currentAction = null;
this.markerActionHandler.onMarkerActionDetected(null, null, null);
}
}
}
else if (selected != currentAction)
{
currentAction = selected;
lastSeen = now;
ArrayList<MarkerImage> markerImages = null;
if (this.markerDrawer != null)
{
Marker markerObject = null;
for (Marker possibleMarkerObject : markers)
{
if (possibleMarkerObject.toString().equals(currentAction.getCodes().get(0)))
{
markerObject = possibleMarkerObject;
}
}
if (markerObject != null)
{
final Rect boundingRect = Imgproc.boundingRect(contours.get(markerObject.markerIndex));
Mat thumbnailMat = this.markerDrawer.drawMarker(markerObject, contours, hierarchy, boundingRect, null);
Bitmap thumbnail = Bitmap.createBitmap(thumbnailMat.width(), thumbnailMat.height(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(thumbnailMat, thumbnail);
MarkerImage markerImage = new MarkerImage(markerObject.toString(), thumbnail, (float) (boundingRect.tl().x / sourceImageSize.width), (float) (boundingRect.tl().y / sourceImageSize.height), (float) (boundingRect.width / sourceImageSize.width), (float) (boundingRect.height / sourceImageSize.height));
markerImages = new ArrayList<>(1);
markerImages.add(markerImage);
Log.i("SOURCEIMG", "w" + sourceImageSize.width + " h" + sourceImageSize.height);
}
}
this.markerActionHandler.onMarkerActionDetected(currentAction, currentAction, markerImages);
}
else
{
for (Marker possibleMarkerObject : markers)
{
String marker = possibleMarkerObject.toString();
for(String code: currentAction.getCodes())
{
if(code.equals(marker))
{
lastSeen = now;
return;
}
}
}
}
}
}