当前位置: 首页 > 知识库问答 >
问题:

Android CameraX |颜色检测

危飞文
2023-03-14

我正在Android上使用新的CameraX。

我做了一个基本的应用程序(类似于“入门”),其中我有一个相机预览和一个亮度分析器。每秒钟我都会在文本视图中显示我的LUMONITY。

现在,按照CameraX指南,我想做颜色检测。每隔一秒钟左右,我想让屏幕中央像素的颜色。

事实上,我不知道如何按照与光度分析器相同的结构进行颜色检测。

光度分析仪等级:

class LuminosityAnalyzer : ImageAnalysis.Analyzer {

private var lastTimeStamp = 0L
private val TAG = this.javaClass.simpleName
var luma = BehaviorSubject.create<Double>()

override fun analyze(image: ImageProxy, rotationDegrees: Int) {
    val currentTimeStamp = System.currentTimeMillis()
    val intervalInSeconds = TimeUnit.SECONDS.toMillis(1)
    val deltaTime = currentTimeStamp - lastTimeStamp
    if(deltaTime >= intervalInSeconds) {
        val buffer = image.planes[0].buffer
        val data = buffer.toByteArray()
        val pixels = data.map { it.toInt() and 0xFF }
        luma.onNext(pixels.average())
        lastTimeStamp = currentTimeStamp
        Log.d(TAG, "Average luminosity: ${luma.value}")
    }


private fun ByteBuffer.toByteArray(): ByteArray {
    rewind()
    val data = ByteArray(remaining())
    get(data)
    return data
}
}

主要活动:

/* display the luminosity */
private fun createLuminosityAnalyzer(): ImageAnalysis{
    val analyzerConfig = ImageAnalysisConfig.Builder().apply {
        setLensFacing(lensFacing)
        setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
    }.build()

    val analyzer = ImageAnalysis(analyzerConfig).apply {
        val luminosityAnalyzer = LuminosityAnalyzer()
        luminosityAnalyzer.luma
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
            // success
            luminosity.text = it.toString()
        },{
            // error
            Log.d(TAG, "Can not get luminosity :(")
        })
        setAnalyzer(executor, luminosityAnalyzer)
    }
    return analyzer
}

除了成为色彩分析仪,我如何做同等的事情?

共有2个答案

戚晨
2023-03-14

所以我想出了自己的办法

颜色分析仪类:

class ColorAnalyzer : ImageAnalysis.Analyzer {

private var lastTimeStamp = 0L
private val TAG = this.javaClass.simpleName
var hexColor = BehaviorSubject.create<Any>()

/* every 100ms, analyze the image we receive from camera */
override fun analyze(image: ImageProxy, rotationDegrees: Int) {
    val currentTimeStamp = System.currentTimeMillis()
    val intervalInMilliSeconds = TimeUnit.MILLISECONDS.toMillis(100)
    val deltaTime = currentTimeStamp - lastTimeStamp
    if(deltaTime >= intervalInMilliSeconds) {

        val imageBitmap = image.image?.toBitmap()
        val pixel = imageBitmap!!.getPixel((imageBitmap.width/2), (imageBitmap.height/2))
        val red = Color.red(pixel)
        val blue = Color.blue(pixel)
        val green = Color.green(pixel)
        hexColor.onNext(String.format("#%02x%02x%02x", red, green, blue))
        Log.d(TAG, "Color: ${hexColor.value}")

        lastTimeStamp = currentTimeStamp
    }
}

// convert the image into a bitmap
private fun Image.toBitmap(): Bitmap {
    val yBuffer = planes[0].buffer // Y
    val uBuffer = planes[1].buffer // U
    val vBuffer = planes[2].buffer // V

    val ySize = yBuffer.remaining()
    val uSize = uBuffer.remaining()
    val vSize = vBuffer.remaining()

    val nv21 = ByteArray(ySize + uSize + vSize)

    yBuffer.get(nv21, 0, ySize)
    vBuffer.get(nv21, ySize, vSize)
    uBuffer.get(nv21, ySize + vSize, uSize)

    val yuvImage = YuvImage(nv21, ImageFormat.NV21, this.width, this.height, null)
    val out = ByteArrayOutputStream()
    yuvImage.compressToJpeg(Rect(0, 0, yuvImage.width, yuvImage.height), 50, out)
    val imageBytes = out.toByteArray()
    return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
}
}

主要活动:

 /* Get the color from Color Analyzer Class */
private fun createColorAnalyzer(): ImageAnalysis{
    val analyzerConfig = ImageAnalysisConfig.Builder().apply {
        setLensFacing(lensFacing)
        setImageReaderMode(ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
    }.build()

    val analyzer = ImageAnalysis(analyzerConfig).apply {
        val colorAnalyzer = ColorAnalyzer()
        colorAnalyzer.hexColor
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                // success
                colorName.text = it.toString() //hexa code in the textView
                colorName.setBackgroundColor(Color.parseColor(it.toString())) //background color of the textView
                (sight.drawable as GradientDrawable).setStroke(10, Color.parseColor(it.toString())) //border color of the sight in the middle of the screen
            },{
                // error
                Log.d(TAG, "Can not get color :(")
            })
        setAnalyzer(executor, colorAnalyzer)
    }
    return analyzer
}

希望对某人有用;)

编辑:

如果您阅读@Minhaz答案,请通过图像获取颜色-

这是使用静态编程语言的Minhaz答案。

颜色分析仪类:

class ColorAnalyzer : ImageAnalysis.Analyzer {

private var lastAnalyzedTimestamp = 0L


private fun ByteBuffer.toByteArray(): ByteArray {
    rewind()    // Rewind the buffer to zero
    val data = ByteArray(remaining())
    get(data)   // Copy the buffer into a byte array
    return data // Return the byte array
}


private fun getRGBfromYUV(image: ImageProxy): Triple<Double, Double, Double> {
    val planes = image.planes

    val height = image.height
    val width = image.width

    // Y
    val yArr = planes[0].buffer
    val yArrByteArray = yArr.toByteArray()
    val yPixelStride = planes[0].pixelStride
    val yRowStride = planes[0].rowStride

    // U
    val uArr = planes[1].buffer
    val uArrByteArray =uArr.toByteArray()
    val uPixelStride = planes[1].pixelStride
    val uRowStride = planes[1].rowStride

    // V
    val vArr = planes[2].buffer
    val vArrByteArray = vArr.toByteArray()
    val vPixelStride = planes[2].pixelStride
    val vRowStride = planes[2].rowStride

    val y = yArrByteArray[(height * yRowStride + width * yPixelStride) / 2].toInt() and 255
    val u = (uArrByteArray[(height * uRowStride + width * uPixelStride) / 4].toInt() and 255) - 128
    val v = (vArrByteArray[(height * vRowStride + width * vPixelStride) / 4].toInt() and 255) - 128

    val r = y + (1.370705 * v)
    val g = y - (0.698001 * v) - (0.337633 * u)
    val b = y + (1.732446 * u)

    return Triple(r,g,b)
}


// analyze the color
override fun analyze(image: ImageProxy, rotationDegrees: Int) {
    val currentTimestamp = System.currentTimeMillis()
    if (currentTimestamp - lastAnalyzedTimestamp >= TimeUnit.MILLISECONDS.toMillis(100)) {

        val colors = getRGBfromYUV(image)
        var hexColor = String.format("#%02x%02x%02x", colors.first.toInt(), colors.second.toInt(), colors.third.toInt())
        Log.d("test", "hexColor: $hexColor")

        lastAnalyzedTimestamp = currentTimestamp
    }

}
}
隗高旻
2023-03-14

如评论中所述,如果您的目标是仅获取中心像素颜色,则将整个YUV图像转换为位图,然后分析中心值的逻辑可能非常低效。您可以通过瞄准正确的像素直接查看YUV图像中的颜色。在YUV图像中,有三个平面,一个代表Y(每像素1字节)和U

planes = imageProxy.getPlanes()

val height = imageProxy.getHeight()
val width = imageProxy.getWidth()

// You may have to find the logic to get array from ByteBuffer
// Y
val yArr = planes[0].buffer.array()
val yPixelStride = planes[0].getPixelStride()
val yRowStride = planes[0].getRowStride()

// U
val uArr = planes[1].buffer.array()
val uPixelStride = planes[1].getPixelStride()
val uRowStride = planes[1].getRowStride()

// V
val vArr = planes[2].buffer.array()
val vPixelStride = planes[2].getPixelStride()
val vRowStride = planes[2].getRowStride()

val y = yArr[(height * yRowStride + width * yPixelStride) / 2] & 255 
val u = (uArr[(height * uRowStride + width * uPixelStride) / 4] & 255) - 128
val v = (vArr[(height * vRowStride + width * vPixelStride) / 4] & 255) - 128 

val r = y + (1.370705 * v);
val g = y - (0.698001 * v) - (0.337633 * u);
val b = y + (1.732446 * u);

魔法值参考:https://en.wikipedia.org/wiki/YUV#YUV420sp_(NV21)_to_RGB_conversion_(Android)

尝试在静态编程语言代码中使用此逻辑,看看它是否工作正常,并且对于实时操作来说是否快速。这肯定会将O(高度*宽度)操作降低到恒定的时间复杂度。

 类似资料:
  • 问题内容: 我希望在Java中实现一项功能,该功能可以读取图像并能够检测红色,蓝色,绿色,黄色等阴影,作为卫星图像分析程序的一部分。因此,例如在标准卫星图像中,蓝色将是水,因此我希望程序读取多少像素是蓝色的,然后它可以说图像的x%是水。 我知道通过读取每个像素的RGB值可以使用整个逻辑语句负载,但是有没有更简单的方法呢?否则,将有数百个if语句,这些语句将花费很长时间来编写,但执行起来也会很长。理

  • 我能够从照片中捕捉颜色的RGB值,但我希望能够通过编程检测该颜色是红色、橙色、黄色、绿色、蓝色、紫色、棕褐色还是白色或黑色。 所以我需要指定返回的RGB范围,例如,红色的值。。。或者蓝色。。。等等我现在有类似的东西,但它不包括所有可能的RGB品种。 红色 R=255,克 R=255,G=0,B 橙色 R=255,克 R=240,G=255,B=0 等等 有人知道如何获取任何RGB值,并检测它是红色

  • 原文:Specifying Colors 在 matplotlib 的几乎所有地方,用户都可以指定颜色,它可以以如下形式提供: RGB 或者 RGBA 浮点值元组,[0, 1]之间,例如(0.1, 0.2, 0.5)或者(0.1, 0.2, 0.5, 0.3)。 RGB 或者 RGBA 十六进制字符串,例如#0F0F0F或者#0F0F0F0F。 [0, 1]之间的浮点值的字符串表示,用于表示灰度,

  • 用法 这是一个基于 material design 基础颜色的调色板。每一种颜色的定义有一个基本的颜色类和一个可选的减轻或变暗的类。 背景颜色 应用一个背景颜色只需要增加颜色的名称和颜色深浅度到元素的 class 属性中。这是一个卡片面板带一个 teal、lighten-2 类。 <div class="card-panel teal lighten-2">这是一个卡片面板带一个 teal lig

  • 在前面的教程中我们已经简要提到过该如何在OpenGL中使用颜色(Color),但是我们至今所接触到的都是很浅层的知识。本节我们将会更深入地讨论什么是颜色,并且还会为接下来的光照(Lighting)教程创建一个场景。 现实世界中有无数种颜色,每一个物体都有它们自己的颜色。我们需要使用(有限的)数值来模拟真实世界中(无限)的颜色,所以并不是所有现实世界中的颜色都可以用数值来表示的。然而我们仍能通过数值

  • 实现可视化要经常和颜色打交道。虽然你的电脑显示屏懂得很多的颜色,但这对通过js来配置颜色帮助不大。所以d3提供多种颜色空间的表示,包括 RGB, HSL,LAB 和 HCL,可实现规范、插值、转换和操作(例如颜色的明暗)。 注意:虽然你可以直接操作颜色,当时也需要参考一下D3对于interpolateRgb, interpolateHsl 和 scales等内置颜色插值的实现。 如果你想查阅调色盘