ScriptIntrincisConvolve3x3: Распределение выходных данных float4 вместо U8_4?
У меня нет проблем с применением функции ScriptIntrinsicConvolve3x3 (или 5x5) для распределения на входе и выходе как U8_4. Но если я хочу применить свертку к градиентному фильтру, такому как Sobel, мне нужен вывод типа float (не U8_4), потому что мне нужно учитывать также отрицательные выходные значения. Этот вопрос был поднят здесь уже 18 месяцев назад, но пока не получил ответа. Любая помощь высоко ценится.
1 ответ
Решение
Хорошо, ниже у вас есть все важные части. Это было скопировано из рабочего кода, надеюсь, я ничего не пропустил. Вычисление величины градиента в Java с использованием out
а также out2
ассигнования оставлены в качестве упражнения для читателя.;) Опять же, было бы намного быстрее (и чище) сделать все это за один проход Renderscript.
public class MainActivity {
private RenderScript mRS;
private Allocation mInAllocation;
Type.Builder TypeIn;
private void createScript(Bitmap mBitmapIn) {
mRS = RenderScript.create(this);
TypeIn = new Type.Builder(mRS, Element.F32_4(mRS));
mInAllocation = createFromBitmap_F32_4(mRS, mBitmapIn);
mScriptConvolve = ScriptIntrinsicConvolve3x3.create(mRS,
Element.F32_4(mRS));
}
private Allocation createFromBitmap_F32_4(RenderScript rs, Bitmap b)
{
int w = b.getWidth();
int h = b.getHeight();
int idx = 0;
Allocation atn = Allocation.createTyped(mRS, TypeIn.setX(w).setY(h).create());
float []temp = new float[w * h * 4];
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
int pix = b.getPixel(x, y);
temp[idx++] = 255.f;
temp[idx++] = (float)((pix >>> 16) & 0xff);
temp[idx++] = (float)((pix >>> 8) & 0xff);
temp[idx++] = (float)(pix & 0xff);
}
atn.copyFrom(temp);
return atn;
}
private void allocationToBitmap(Allocation atn, Bitmap bmp)
{
int w = bmp.getWidth();
int h = bmp.getHeight();
int idx = 0;
float []temp = new float[w * h * 4];
atn.copyTo(temp);
for(int y = 0; y < h; y++)
for(int x = 0; x < w; x++)
{
int a = 255; idx++;
int r = Math.min(255, Math.max(0, (int)temp[idx++]));
int g = Math.min(255, Math.max(0, (int)temp[idx++]));
int b = Math.min(255, Math.max(0, (int)temp[idx++]));
bmp.setPixel(x, y, (a << 24 | r << 16 | g << 8 | b));
}
}
private void performFilter(Allocation inAllocation,
Bitmap bitmapOut) {
Allocation out = Allocation.createTyped(mRS, TypeIn.create());
Allocation out2 = Allocation.createTyped(mRS, TypeIn.create());
// Emboss filter kernel
float coefficients[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
float coefficients2[] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};
mScriptConvolve.setCoefficients(coefficients);
mScriptConvolve.setInput(inAllocation);
mScriptConvolve.forEach(out); // Gx
mScriptConvolve.setCoefficients(coefficients2);
mScriptConvolve.setInput(inAllocation);
mScriptConvolve.forEach(out2); // Gy
allocationToBitmap(out2, bitmapOut);
}