Commit 9402151f authored by Gayan Bandara IT19954738's avatar Gayan Bandara IT19954738

Merge branch 'IT19954738' into 'master'

Result view functions added

See merge request !12
parents aab47ff5 45b386e5
package com.sliit.lkrdetectionandroid;
import android.graphics.Rect;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
class Result {
int classIndex;
Float score;
Rect rect;
public Result(int cls, Float output, Rect rect) {
this.classIndex = cls;
this.score = output;
this.rect = rect;
}
};
public class PrePostProcessor {
// for yolov5 model, no need to apply MEAN and STD
static float[] NO_MEAN_RGB = new float[] {0.0f, 0.0f, 0.0f};
static float[] NO_STD_RGB = new float[] {1.0f, 1.0f, 1.0f};
// model input image size
static int mInputWidth = 640;
static int mInputHeight = 640;
// model output is of size 25200*(num_of_class+5)
private static int mOutputRow = 25200; // as decided by the YOLOv5 model for input image of size 640*640
private static int mOutputColumn = 11; // left, top, right, bottom, score and 80 class probability
private static float mThreshold = 0.50f; // score above which a detection is generated
private static int mNmsLimit = 15;
static String[] mClasses;
// The two methods nonMaxSuppression and IOU below are ported from https://github.com/hollance/YOLO-CoreML-MPSNNGraph/blob/master/Common/Helpers.swift
/**
Removes bounding boxes that overlap too much with other boxes that have
a higher score.
- Parameters:
- boxes: an array of bounding boxes and their scores
- limit: the maximum number of boxes that will be selected
- threshold: used to decide whether boxes overlap too much
*/
static ArrayList<Result> nonMaxSuppression(ArrayList<Result> boxes, int limit, float threshold) {
// Do an argsort on the confidence scores, from high to low.
Collections.sort(boxes,
new Comparator<Result>() {
@Override
public int compare(Result o1, Result o2) {
return o1.score.compareTo(o2.score);
}
});
ArrayList<Result> selected = new ArrayList<>();
boolean[] active = new boolean[boxes.size()];
Arrays.fill(active, true);
int numActive = active.length;
// The algorithm is simple: Start with the box that has the highest score.
// Remove any remaining boxes that overlap it more than the given threshold
// amount. If there are any boxes left (i.e. these did not overlap with any
// previous boxes), then repeat this procedure, until no more boxes remain
// or the limit has been reached.
boolean done = false;
for (int i=0; i<boxes.size() && !done; i++) {
if (active[i]) {
Result boxA = boxes.get(i);
selected.add(boxA);
if (selected.size() >= limit) break;
for (int j=i+1; j<boxes.size(); j++) {
if (active[j]) {
Result boxB = boxes.get(j);
if (IOU(boxA.rect, boxB.rect) > threshold) {
active[j] = false;
numActive -= 1;
if (numActive <= 0) {
done = true;
break;
}
}
}
}
}
}
return selected;
}
/**
Computes intersection-over-union overlap between two bounding boxes.
*/
static float IOU(Rect a, Rect b) {
float areaA = (a.right - a.left) * (a.bottom - a.top);
if (areaA <= 0.0) return 0.0f;
float areaB = (b.right - b.left) * (b.bottom - b.top);
if (areaB <= 0.0) return 0.0f;
float intersectionMinX = Math.max(a.left, b.left);
float intersectionMinY = Math.max(a.top, b.top);
float intersectionMaxX = Math.min(a.right, b.right);
float intersectionMaxY = Math.min(a.bottom, b.bottom);
float intersectionArea = Math.max(intersectionMaxY - intersectionMinY, 0) *
Math.max(intersectionMaxX - intersectionMinX, 0);
return intersectionArea / (areaA + areaB - intersectionArea);
}
static ArrayList<Result> outputsToNMSPredictions(float[] outputs, float imgScaleX, float imgScaleY, float ivScaleX, float ivScaleY, float startX, float startY) {
ArrayList<Result> results = new ArrayList<>();
for (int i = 0; i< mOutputRow; i++) {
if (outputs[i* mOutputColumn +4] > mThreshold) {
float x = outputs[i* mOutputColumn];
float y = outputs[i* mOutputColumn +1];
float w = outputs[i* mOutputColumn +2];
float h = outputs[i* mOutputColumn +3];
float left = imgScaleX * (x - w/2);
float top = imgScaleY * (y - h/2);
float right = imgScaleX * (x + w/2);
float bottom = imgScaleY * (y + h/2);
float max = outputs[i* mOutputColumn +5];
int cls = 0;
for (int j = 0; j < mOutputColumn -5; j++) {
if (outputs[i* mOutputColumn +5+j] > max) {
max = outputs[i* mOutputColumn +5+j];
cls = j;
}
}
Rect rect = new Rect((int)(startX+ivScaleX*left), (int)(startY+top*ivScaleY), (int)(startX+ivScaleX*right), (int)(startY+ivScaleY*bottom));
Result result = new Result(cls, outputs[i*mOutputColumn+4], rect);
results.add(result);
}
}
return nonMaxSuppression(results, mNmsLimit, mThreshold);
}
}
package com.sliit.lkrdetectionandroid;
import static androidx.constraintlayout.helper.widget.MotionEffect.TAG;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import java.util.ArrayList;
public class ResultView extends View {
private final static int TEXT_X = 40;
private final static int TEXT_Y = 35;
private final static int TEXT_WIDTH = 260;
private final static int TEXT_HEIGHT = 50;
private Paint mPaintRectangle;
private Paint mPaintText;
private ArrayList<Result> mResults;
public ResultView(Context context) {
super(context);
}
public ResultView(Context context, AttributeSet attrs){
super(context, attrs);
mPaintRectangle = new Paint();
mPaintRectangle.setColor(Color.YELLOW);
mPaintText = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mResults == null || mResults.size() == 0){
String msg = "Detection faild! Please tap the Check again button to try again";
NoteDetector.textView_result.setText(msg);
return;
}
for (Result result : mResults) {
mPaintRectangle.setStrokeWidth(5);
mPaintRectangle.setStyle(Paint.Style.STROKE);
canvas.drawRect(result.rect, mPaintRectangle);
Path mPath = new Path();
RectF mRectF = new RectF(result.rect.left, result.rect.top, result.rect.left + TEXT_WIDTH, result.rect.top + TEXT_HEIGHT);
mPath.addRect(mRectF, Path.Direction.CW);
mPaintText.setColor(Color.MAGENTA);
canvas.drawPath(mPath, mPaintText);
mPaintText.setColor(Color.WHITE);
mPaintText.setStrokeWidth(0);
mPaintText.setStyle(Paint.Style.FILL);
mPaintText.setTextSize(32);
canvas.drawText(String.format("%s %.2f", PrePostProcessor.mClasses[result.classIndex], result.score), result.rect.left + TEXT_X, result.rect.top + TEXT_Y, mPaintText);
NoteDetector.textView_result.setText("LKR "+ String.format(PrePostProcessor.mClasses[result.classIndex]+" Note Detected"));
}
}
public void setResults(ArrayList<Result> results) {
mResults = results;
}
}
package com.sliit.lkrdetectionandroid;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
public class ResultView2 extends View {
private final static int TEXT_X = 40;
private final static int TEXT_Y = 35;
private final static int TEXT_WIDTH = 260;
private final static int TEXT_HEIGHT = 50;
private Paint mPaintRectangle;
private Paint mPaintText;
private ArrayList<Result> mResults;
public ResultView2(Context context) {
super(context);
}
public ResultView2(Context context, AttributeSet attrs){
super(context, attrs);
mPaintRectangle = new Paint();
mPaintRectangle.setColor(Color.YELLOW);
mPaintText = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mResults == null || mResults.size() == 0){
String msg = "Detection faild! Please tap the 'Add a note' button to try again";
NoteCounter.textView_result.setText(msg);
return;
}
for (Result result : mResults) {
mPaintRectangle.setStrokeWidth(5);
mPaintRectangle.setStyle(Paint.Style.STROKE);
canvas.drawRect(result.rect, mPaintRectangle);
Path mPath = new Path();
RectF mRectF = new RectF(result.rect.left, result.rect.top, result.rect.left + TEXT_WIDTH, result.rect.top + TEXT_HEIGHT);
mPath.addRect(mRectF, Path.Direction.CW);
mPaintText.setColor(Color.MAGENTA);
canvas.drawPath(mPath, mPaintText);
mPaintText.setColor(Color.WHITE);
mPaintText.setStrokeWidth(0);
mPaintText.setStyle(Paint.Style.FILL);
mPaintText.setTextSize(32);
canvas.drawText(String.format("%s %.2f", PrePostProcessor.mClasses[result.classIndex], result.score), result.rect.left + TEXT_X, result.rect.top + TEXT_Y, mPaintText);
String a = String.format(PrePostProcessor.mClasses[result.classIndex]);
int b = Integer.parseInt(a);
NoteCounter.counts.add(b);
NoteCounter.textView_result.setText("LKR "+ String.format(PrePostProcessor.mClasses[result.classIndex]+" Note Detected."));
}
}
public void setResults(ArrayList<Result> results) {
mResults = results;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment