Ok, ниже у вас есть все важные детали. Он был скопирован из рабочего кода, надеюсь, что я ничего не пропустил. Вычислительная градиентная величина в 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);
}
Просто уточнить: вам нужно отдельно сохранить Gx и Gy выход из фильтра Sobel, или вы планируете объединить их для получения величины отрицательного градиента? Если последнее имеет место, вам временно нужны отрицательные значения. Будет намного быстрее иметь собственный скрипт, который вычисляет как свертки Gx, так и Gy за один проход и сохраняет комбинированный результат в U8_4. –
Miloslaw, хороший пункт. Действительно, было бы здорово получить массив амплитуд плюс массив направлений в одном проходе Renderscript. Я не хочу быть жалким, но, к сожалению, после трех недель интенсивного исследования Renderscript я отставку, так как нет документации, и я хочу понять, что я делаю. Кроме того, я даже пытаюсь создать смешную папку .rs с rs. скрипт, который распознается Java как объект Script_C .... Поэтому я стараюсь оптимально использовать Внутренние функции (например, Gauss Blur), и решение этой проблемы Sobel принесет мне необходимую мне скорость. – Settembrini
Это можно сделать, но будет далек от оптимального: вам придется преобразовать данные растрового изображения в float сперва, так как ScriptIntrinsicConvolve3x3 требует ввода и вывода Allocations того же типа. Затем вы получите два прохода ядра и, наконец, преобразование в градиентную величину в Java. Я бы (снова) предложил вам попробовать «Импортировать образец ...» в пустой проект, чтобы вы могли анализировать скрипты сборки и т. Д. И, кстати, как вы установили папку «rs»? Рукой или с помощью папки «Новая папка/Renderscript»? Потому что я только что сделал последний в чистом проекте, и он работал как шарм. –