2014-09-12 6 views
0

큰 이미지의 경우 Java를 사용하여 처리하는 데 오랜 시간이 걸리기 때문에 이미지 처리 코드를 최적화하려고합니다.RenderScript 출력에 부울 배열을 어떻게 할당 할 수 있습니까?

나는 DDMS 몇 가지 방법 프로파일 링을했고, CPU 시간의 거의 50 %까지 먹는이 방법을 발견

private int getBrightness(int color) { 
    // returns an int from 0-255 where zero is pure black and 255 is pure white, 
    // weighted to correspond to perceived brightness 
    // http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx 
    int red = Color.red(color); 
    int blue = Color.blue(color); 
    int green = Color.green(color); 
    int brightness = (int) Math.round(Math.sqrt((0.241 * red * red) + (0.691 * green * green) + (0.068 * blue * blue))); 
    return brightness; 
} 

특히, Math.sqrt()와 Math.round에 대한 호출()가 진짜를 범인. 이것은 병렬 처리가 가능할 때 연속적으로 계산된다는 사실과 결합되어 처리가 너무 오래 걸린다는 것을 의미합니다.

누군가가 RenderScript를 지적했습니다. 나는 내가하려고하는 것에 완벽하게 들린다 고 생각했다. C++가 아닌 C를 알고 있으며, 내가 성취하고자하는 일에 어려움을 겪고 있습니다.

기본적으로 처리 시간에는 각 픽셀의 실제 밝기를 알 필요가 없습니다. 임계 값보다 높거나 낮 으면 (이 개체의 수명 동안 변경되지 않음). 따라서 픽셀이> 임계 값 (true)인지 또는 < 임계 값 (false)인지 알려주는 부울 값 배열을 간단히 만들 수 있습니다. 그래서 renderscript에서 C 코드로 밝기 계산을 옮길 수 있습니다.

ouput Allocation에 true 또는 false 값을 직접 반환하고 싶습니다. 이것이 제가 문제가되는 것입니다. 여기

내 Renderscript C 코드 :

#pragma version(1) 
#pragma rs java_package_name(com.mushroomhouse.pixelbomb) 
#pragma rs_fp_relaxed 

int threshold = 160; 

bool __attribute__((kernel)) generate(uchar4 in) { 
    int r = (int) (255*sqrt((float)((0.241 * in.r * in.r) + (0.691 * in.g * in.g) + (0.068 * in.b * in.b)))); 
    return (r>threshold); 
} 

그리고 여기 내 처리 클래스의 관련 코드입니다 :

(Member variables) 
... 
RenderScript myRS; 
ScriptC_brightness_map script; 
Allocation allocIn, allocOut; 
boolean[][] truthMap; 

(Public Constructor) { 
    ... 
    myRS = RenderScript.create(context); 
    script = new ScriptC_brightness_map(myRS);  
} 

(Initialization before processing is done) 
... 
truthMap = new boolean[width][height]; 
allocIn = Allocation.createFromBitmap(myRS, product); 
allocOut = ???? 
script.set_threshold(brightnessValue); 
script.forEach_generate(allocIn, allocOut); 
... 

(Processing) 

그래서,

  1. 어떻게 allocOut를 초기화 할 , 부울 [] []로 복사 할 수있는 할당이 필요합니다.

  2. 즉시 부울 [] [] truthMap에 allocOut를 복사 할 수 있습니까? 아니면 콜백을 사용해야합니까? 나는 RenderScript가 비동기 적이기 때문에 문제가 발생할 것이라고 읽었습니다.

처리가 백그라운드에서 IntentService를 통해 수행되므로 RenderScript를 기다리는 것이 문제가되지 않습니다.

또 다른 옵션은 Renderscript가 단순히 계산 된 밝기 값을 반환하도록하는 것이고 Java 코드에서 비교할 수 있습니다. 조금 느려질 수도 있지만 이것이 유일한 방법 일 경우, 나는 그걸로 살 수 있습니다. 그러나 나는 그런 일을하는 방법에 관해서는 여전히 완전히 잃어버린다. inAlloc과 outAlloc을 동일한 차원의 비트 맵으로 만드는 방법에 대한 자습서가 많이 있지만 실제로는 다른 출력 할당에 대해서는 찾을 수 없습니다.

도움 주셔서 감사합니다.

답변

2

몇 가지.

우선 C99 스펙에 따르면 한정자가없는 함수 (예 : 0.53 또는 그와 비슷한 것)에 부동 소수점 상수가있는 경우 기술적으로 배정도가 높습니다. 즉, 그들은 입니다. 배정 밀도가 필요하다는 것을 알지 못하는 한, 아마도 이걸 필요로하지 않을 것입니다. 이처럼 간단한 이미지 처리를 위해서는 꼭 필요하지 않습니다.상수 (예 : 0.53f)에 f를 추가하면 단 정밀도 값으로 처리됩니다.

allocOut에 대한 할당이 필요합니다. 가장 쉬운 방법은 Type.Builder를 사용하는 것입니다. 비트 맵과 동일한 크기의 Element.BOOLEAN으로 2D 유형을 작성하십시오. 다시 복사하려면 boolean[][]이 아니라 boolean[]으로 복사하고 truthMap[y * width + x]을 사용하여 색인을 생성하고 싶습니다. IIRC를 사용하는 경우 을 사용하여 해당 크기가 할당의 너비 * 높이 인 한 boolean[]에 데이터를 가져올 수 있습니다.

복사 할 수 없다면 (오랫동안 Java 논리 연산을 처리하지 못했지만) RS 요소로 바이트 []와 Element.U8을 전환하고 대신 0 또는 1을 쓸 수 있습니다 거짓/참.

+0

수 프림에 감사드립니다. 나는 나의 접근 방식을 바꾸었고 나는 그것이 작동하도록하는 것에 매우 가깝다. 나는 내 질문의 끝에서 RenderScript가 int foreach를 반환하고이를 int [] brightnessMap에 복사하도록 제안한 바를 수행했다. 이제 런타임 오류가 발생합니다. 입력 및 출력 매개 변수 사이의 차원이 일치하지 않습니다. 'allocOut = Allocation.createSized (myRS, Element.I32 (myRS), brightnessMap.length); ' 그래서 2 차원 할당을해야한다고 가정합니다. 그걸 보면서. 통찰력을 가져 주셔서 감사합니다. – Eric

+1

예, 입력 및 출력 할당이 동일한 치수 (x 및 y)를 가져야하지만 2D 할당이 1D Java 배열에 복사 할 수 있다고 생각합니다. –