-
Notifications
You must be signed in to change notification settings - Fork 14
/
OpenCVRoteterter.kt
79 lines (60 loc) · 2.62 KB
/
OpenCVRoteterter.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package ru.gordinmitya.yuv2buf_demo
import android.graphics.Bitmap
import android.graphics.ImageFormat
import androidx.camera.core.ImageProxy
import org.opencv.android.Utils
import org.opencv.core.Core
import org.opencv.core.CvType
import org.opencv.core.Mat
import org.opencv.imgproc.Imgproc
import ru.gordinmitya.yuv2buf.Yuv
import java.nio.ByteBuffer
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
// Here I try to rotate image in YUV format because it's 2x smaller than RGB
class OpenCVRoteterter() : ImageConverter {
override fun getName(): String = "OpenCV (YUV rotate)"
private var reuseBuffer: ByteBuffer? = null
override fun convert(image: ImageProxy): ConversionResult {
val tik = System.currentTimeMillis()
val converted = Yuv.toBuffer(image, reuseBuffer)
reuseBuffer = converted.buffer
val format = when (converted.type) {
ImageFormat.YUV_420_888 -> Imgproc.COLOR_YUV2RGB_I420
ImageFormat.NV21 -> Imgproc.COLOR_YUV2RGB_NV21
else -> throw IllegalArgumentException()
}
val ySize = image.width * image.height
val cSize = ySize / 4
val yBuf = converted.buffer
val uvBuf = converted.buffer.clipBuffer(ySize, cSize + cSize)
val yMat = Mat(image.height, image.width, CvType.CV_8UC1, yBuf)
val uvMat = Mat(image.height / 2, image.width / 2, CvType.CV_8UC2, uvBuf)
val tRotateStart = System.currentTimeMillis()
if (image.imageInfo.rotationDegrees != 0) {
Core.rotate(yMat, yMat, image.imageInfo.rotationDegrees / 90 - 1)
Core.rotate(uvMat, uvMat, image.imageInfo.rotationDegrees / 90 - 1)
}
val tRotateEnd = System.currentTimeMillis()
val rgbMat = Mat(image.height, image.width, CvType.CV_8UC3)
Imgproc.cvtColorTwoPlane(yMat, uvMat, rgbMat, format)
val tok = System.currentTimeMillis()
val bitmap = Bitmap.createBitmap(rgbMat.cols(), rgbMat.rows(), Bitmap.Config.ARGB_8888)
Utils.matToBitmap(rgbMat, bitmap)
// don't forget to call image.close() here
// but as long as we have many converters
// we'll do it in CompositeConverter
// image.close()
val colorTime = tRotateStart - tik + tok - tRotateEnd
return ConversionResult.Success(getName(), bitmap, colorTime, tRotateEnd - tRotateStart)
}
private fun ByteBuffer.clipBuffer(
start: Int,
size: Int
): ByteBuffer? {
val duplicate = this.duplicate()
duplicate.position(start)
duplicate.limit(start + size)
return duplicate.slice()
}
}