0

我必须在 Android 中使用 RenderScript 从 ARGB 数组创建 HSV 直方图。这是我第一次使用 RenderScript,我不确定我是否犯了错误,因为性能不是很好。从 1920x1080 位图创建 HSV 直方图需要 100 到 150 毫秒。

渲染脚本代码:

#pragma version(1)
#pragma rs java_package_name(com.test.renderscript)
#pragma rs_fp_relaxed

uchar3 bins;
rs_allocation histogramAllocation;

void __attribute__((kernel)) process(uchar4 in) {

    float r = in.r / 255.0;
    float g = in.g / 255.0;
    float b = in.b / 255.0;

    // convert rgb to hsv

    float minRGB = min( r, min( g, b ) );
    float maxRGB = max( r, max( g, b ) );
    float deltaRGB = maxRGB - minRGB;

    float h = 0.0;
    float s = maxRGB == 0 ? 0 : (maxRGB - minRGB) / maxRGB;
    float v = maxRGB;

    if (deltaRGB != 0) {

        if (r == maxRGB) {
            h = (g - b) / deltaRGB;
        }
        else {
            if (g == maxRGB) {
                h = 2 + (b - r) / deltaRGB;
            }
            else {
                h = 4 + (r - g) / deltaRGB;
            }
        }

        h *= 60;
        if (h < 0) { h += 360; }
        if (h == 360) { h = 0; }
    }

    // quantize hsv

    uint qh = h / (360.0 / bins.s0);
    uint qs = (s * 100) / (101.0 / bins.s1);
    uint qv = (v * 100) / (101.0 / bins.s2);

    // calculate bin index and update the count at that index
    // (v * bin size H * bin size S) + (s * bin size H) + h;
    uint binIndex = (qv * bins.s0 * bins.s1) + (qs * bins.s0) + qh;
    uint count = rsGetElementAt_uint(histogramAllocation, binIndex);
    rsSetElementAt_uint(histogramAllocation, (count + 1), binIndex);
}


void init() {

    uint histogramSize = bins.s0 * bins.s1 * bins.s2;
    for (int i=0; i < histogramSize; i++) {
        rsSetElementAt_uint(histogramAllocation, 0, i);
    }
}

科特林代码:

class RsCreateHsvHistogram {

    fun execute(rs: RenderScript, src: ByteArray, bins: HsvHistogram.Bins = HsvHistogram.Bins()): HsvHistogram {

        val start = SystemClock.elapsedRealtimeNanos()

        val histogramSize = bins.h * bins.s * bins.v

        // create input allocation
        val typeIn = Type.Builder(rs, Element.U8_4(rs))
            .setX(src.size / 4)
            .create()

        val allocIn = Allocation.createTyped(rs, typeIn)
        allocIn.copyFrom(src)

        // create output allocation -> the histogram allocation
        val typeOut = Type.Builder(rs, Element.I32(rs))
            .setX(histogramSize)
            .create()

        val allocOut = Allocation.createTyped(rs, typeOut)

        // run the render script
        val script = ScriptC_create_hsv_histogram(rs)
        script._bins = Short3(bins.h, bins.s, bins.v)
        script._histogramAllocation = allocOut
        script.forEach_process(allocIn)

        // copy output allocation to histogram array
        val histogramData = IntArray(histogramSize)
        allocOut.copyTo(histogramData)

        val stop = SystemClock.elapsedRealtimeNanos()
        Timber.e("duration => ${(stop-start) / 1000000.0} ms")

        return HsvHistogram(histogramData, bins)
    }
}

我希望你能帮助我提高性能。您认为 HSV 直方图的创建可以在 20 毫秒左右完成吗?这是现实的吗?

4

0 回答 0