@@ -34,57 +34,56 @@ class ImageSegmentationModel(
34
34
}
35
35
36
36
private fun extractResults (
37
- result : Array < Float > ,
37
+ result : FloatArray ,
38
38
numLabels : Int ,
39
39
resize : Boolean ,
40
- ): List <Mat > {
40
+ ): List <FloatArray > {
41
41
val modelSize = getModelImageSize()
42
42
val numModelPixels = (modelSize.height * modelSize.width).toInt()
43
43
44
- val extractedLabelScores = mutableListOf<Mat >()
44
+ val extractedLabelScores = mutableListOf<FloatArray >()
45
45
46
46
for (label in 0 .. < numLabels) {
47
- val mat = Mat (modelSize, CvType .CV_32F )
48
-
49
- for (pixel in 0 .. < numModelPixels) {
50
- val row = pixel / modelSize.width.toInt()
51
- val col = pixel % modelSize.width.toInt()
52
- val v = floatArrayOf(result[label * numModelPixels + pixel])
53
- mat.put(row, col, v)
54
- }
47
+ // Calls to OpenCV via JNI are very slow so we do as much as we can
48
+ // with pure Kotlin
49
+ val range = IntRange (label * numModelPixels, (label + 1 ) * numModelPixels - 1 )
50
+ val pixelBuffer = result.slice(range).toFloatArray()
55
51
56
52
if (resize) {
53
+ // Rescale the image with OpenCV
54
+ val mat = Mat (modelSize, CvType .CV_32F )
55
+ mat.put(0 , 0 , pixelBuffer)
57
56
val resizedMat = Mat ()
58
57
Imgproc .resize(mat, resizedMat, originalSize)
59
- extractedLabelScores.add(resizedMat)
58
+ val resizedBuffer = FloatArray ((originalSize.height * originalSize.width).toInt())
59
+ resizedMat.get(0 , 0 , resizedBuffer)
60
+ extractedLabelScores.add(resizedBuffer)
60
61
} else {
61
- extractedLabelScores.add(mat )
62
+ extractedLabelScores.add(pixelBuffer )
62
63
}
63
64
}
64
65
return extractedLabelScores
65
66
}
66
67
67
68
private fun adjustScoresPerPixel (
68
- labelScores : List <Mat >,
69
+ labelScores : List <FloatArray >,
69
70
numLabels : Int ,
70
71
outputSize : Size ,
71
- ): Mat {
72
- val argMax = Mat (outputSize, CvType .CV_32S )
72
+ ): IntArray {
73
73
val numPixels = (outputSize.height * outputSize.width).toInt()
74
+ val argMax = IntArray (numPixels)
74
75
for (pixel in 0 .. < numPixels) {
75
- val row = pixel / outputSize.width.toInt()
76
- val col = pixel % outputSize.width.toInt()
77
76
val scores = mutableListOf<Float >()
78
- for (mat in labelScores) {
79
- scores.add(mat.get(row, col)[ 0 ].toFloat() )
77
+ for (buffer in labelScores) {
78
+ scores.add(buffer[pixel] )
80
79
}
81
80
val adjustedScores = softmax(scores.toTypedArray())
82
81
for (label in 0 .. < numLabels) {
83
- labelScores[label].put(row, col, floatArrayOf( adjustedScores[label]))
82
+ labelScores[label][pixel] = adjustedScores[label]
84
83
}
85
84
86
85
val maxIndex = scores.withIndex().maxBy { it.value }.index
87
- argMax.put(row, col, intArrayOf( maxIndex))
86
+ argMax[pixel] = maxIndex
88
87
}
89
88
90
89
return argMax
@@ -95,14 +94,13 @@ class ImageSegmentationModel(
95
94
classesOfInterest : ReadableArray ,
96
95
resize : Boolean ,
97
96
): WritableMap {
98
- val output = output[0 ].toTensor().dataAsFloatArray.toTypedArray()
97
+ val output = output[0 ].toTensor().dataAsFloatArray
99
98
val modelSize = getModelImageSize()
100
99
val numLabels = deeplabv3_resnet50_labels.size
101
100
102
101
require(output.count() == (numLabels * modelSize.height * modelSize.width).toInt()) { " Model generated unexpected output size." }
103
102
104
103
val outputSize = if (resize) originalSize else modelSize
105
- val numOutputPixels = (outputSize.height * outputSize.width).toInt()
106
104
107
105
val extractedResults = extractResults(output, numLabels, resize)
108
106
@@ -118,28 +116,16 @@ class ImageSegmentationModel(
118
116
119
117
for (label in 0 .. < numLabels) {
120
118
if (labelSet.contains(deeplabv3_resnet50_labels[label])) {
121
- val buffer = FloatArray (numOutputPixels)
122
- for (pixel in 0 .. < numOutputPixels) {
123
- val row = pixel / outputSize.width.toInt()
124
- val col = pixel % outputSize.width.toInt()
125
- buffer[pixel] = extractedResults[label].get(row, col)[0 ].toFloat()
126
- }
127
119
res.putArray(
128
120
deeplabv3_resnet50_labels[label],
129
- ArrayUtils .createReadableArrayFromFloatArray(buffer ),
121
+ ArrayUtils .createReadableArrayFromFloatArray(extractedResults[label] ),
130
122
)
131
123
}
132
124
}
133
125
134
- val argMaxBuffer = IntArray (numOutputPixels)
135
- for (pixel in 0 .. < numOutputPixels) {
136
- val row = pixel / outputSize.width.toInt()
137
- val col = pixel % outputSize.width.toInt()
138
- argMaxBuffer[pixel] = argMax.get(row, col)[0 ].toInt()
139
- }
140
126
res.putArray(
141
127
" argmax" ,
142
- ArrayUtils .createReadableArrayFromIntArray(argMaxBuffer ),
128
+ ArrayUtils .createReadableArrayFromIntArray(argMax ),
143
129
)
144
130
145
131
return res
0 commit comments