Help tiny yolo v2
@EmmaNingMS is already working on this.
Since Nov 6, 2019.
- Dominant language
- Jupyter Notebook
- Stars
- 9.8k
- Forks
- 1.6k
- PR merge metrics
- No merged PRs in 30d
Description
Hello
I want to use the onnx tiny yolo v2 in Android https://github.com/onnx/models/tree/master/vision/object_detection_segmentation/tiny_yolov2
My implementation is based on this one: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/android/src/org/tensorflow/demo/TensorFlowYoloDetector.java
I made it work but I always get (almost) the same output with different inputs (I use the VOC dataset):
[20975] tvmonitor (24.3%) RectF(0.0, 0.0, 415.0, 415.0)
[6600] horse (23.7%) RectF(0.0, 0.0, 401.00543, 399.01813)
[21075] bicycle (22.9%) RectF(0.0, 0.0, 415.0, 415.0)
[14550] aeroplane (21.4%) RectF(0.0, 0.0, 415.0, 415.0)
That's the output of this picture:

I am not sure where is the problem, if I do the pre/post-processing wrong or the model is not correct. Because I tried to use the model from the original website with the same images and it works nice.
This is my preprocessing:
public float[] getFloatArrayFromResizedImage(Bitmap bm,int reqCH, int reqW, int reqH ) {
int w = bm.getWidth();
int h = bm.getHeight();
if (reqW != w || reqH != h ){
bm = resizeImage(bm, reqW, reqH);
w = bm.getWidth();
h = bm.getHeight();
}
float[] data = new float[reqCH * w * h];
int[] intValues = new int[w * h];
bm.getPixels(intValues, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
for (int i = 0; i < intValues.length; ++i) {
float r = ((intValues[i] >> 16) & 0xFF) / 255.0f;
float g = ((intValues[i] >> 8) & 0xFF) / 255.0f;
float b = (intValues[i] & 0xFF) / 255.0f;
if(reqCH == 1){
int gray = (int) (r * 0.3 + g * 0.59 + b * 0.11);
data[i] = gray;
} else {
data[i * 3 + 0] = r;
data[i * 3 + 1] = g;
data[i * 3 + 2] = b;
}
}
return data;
}
I know that the input format is NCHW, in this case, 1x3x416x416, I just wonder what it means, should I feed the model with an 1D array of size 3x416x416 in this format [R,G,B,R,G,B,R,G,B....] (I use this right now) or this one: [R,R,R......, G,G,G.....B,B,B]??
Post-processing:
public List<Classifier.Recognition> postProcess(float[] output1) {
int MAX_RESULTS = 5;
int NUM_CLASSES = 20;
int NUM_BOXES_PER_BLOCK = 5;
final float[] output = output1;
double[] ANCHORS = {
1.08, 1.19,
3.42, 4.41,
6.63, 11.38,
9.42, 5.11,
16.62, 10.52
};
String[] LABELS = {
"aeroplane",
"bicycle",
"bird",
"boat",
"bottle",
"bus",
"car",
"cat",
"chair",
"cow",
"diningtable",
"dog",
"horse",
"motorbike",
"person",
"pottedplant",
"sheep",
"sofa",
"train",
"tvmonitor"
};
int blockSize = 32;
final int gridWidth = 416 / blockSize;
final int gridHeight = 416 / blockSize;
//https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/android/src/org/tensorflow/demo/Classifier.java
final PriorityQueue<Classifier.Recognition> pq =
new PriorityQueue<Classifier.Recognition>(
1,
new Comparator<Classifier.Recognition>() {
@Override
public int compare(final Classifier.Recognition lhs, final Classifier.Recognition rhs) {
// Intentionally reversed to put high confidence at the head of the queue.
return Float.compare(rhs.getConfidence(), lhs.getConfidence());
}
});
for (int y = 0; y < gridHeight; ++y) {
for (int x = 0; x < gridWidth; ++x) {
for (int b = 0; b < NUM_BOXES_PER_BLOCK; ++b) {
final int offset =
(gridWidth * (NUM_BOXES_PER_BLOCK * (NUM_CLASSES + 5))) * y
+ (NUM_BOXES_PER_BLOCK * (NUM_CLASSES + 5)) * x
+ (NUM_CLASSES + 5) * b;
final float xPos = (x + expit(output[offset + 0])) * blockSize;
final float yPos = (y + expit(output[offset + 1])) * blockSize;
final float w = (float) (Math.exp(output[offset + 2]) * ANCHORS[2 * b + 0]) * blockSize;
final float h = (float) (Math.exp(output[offset + 3]) * ANCHORS[2 * b + 1]) * blockSize;
final float confidence = expit(output[offset + 4]);
int detectedClass = -1;
float maxClass = 0;
final float[] classes = new float[NUM_CLASSES];
for (int c = 0; c < NUM_CLASSES; ++c) {
classes[c] = output[offset + 5 + c];
}
softmax(classes);
for (int c = 0; c < NUM_CLASSES; ++c) {
if (classes[c] > maxClass) {
detectedClass = c;
maxClass = classes[c];
}
}
final float confidenceInClass = maxClass * confidence;
if (confidenceInClass > 0.2) {
final RectF rect =
new RectF(
Math.max(0, xPos - w / 2),
Math.max(0, yPos - h / 2),
Math.min(416 - 1, xPos + w / 2),
Math.min(416 - 1, yPos + h / 2));
System.out.println(LABELS[detectedClass] +", "+ detectedClass +", "+ confidenceInClass+", "+ rect);
pq.add(new Classifier.Recognition("" + offset, LABELS[detectedClass], confidenceInClass, rect));
}
}
}
}
final ArrayList<Classifier.Recognition> recognitions = new ArrayList<Classifier.Recognition>();
for (int i = 0; i < Math.min(pq.size(), MAX_RESULTS); ++i) {
recognitions.add(pq.poll());
}
return recognitions;
}
void softmax(final float[] vals) {
float max = Float.NEGATIVE_INFINITY;
for (final float val : vals) {
max = Math.max(max, val);
}
float sum = 0.0f;
for (int i = 0; i < vals.length; ++i) {
vals[i] = (float) Math.exp(vals[i] - max);
sum += vals[i];
}
for (int i = 0; i < vals.length; ++i) {
vals[i] = vals[i] / sum;
}
}
private float expit(final float x) {
return (float) (1. / (1. + Math.exp(-x)));
}
do I do anything wrong? it seems to me that there is something wrong in the model weights because no matter the input I get almost the same output.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.