Image processing RenderScript';s分配输出返回一个黑色位图
几天前,我刚刚开始学习RenderScript。我设法创建了一些简单的图像处理过滤器,例如灰度、颜色变化。 现在我正在研究Canny边缘过滤器,但没有成功 问题:为什么ImageView显示黑色图像以及如何解决它? 我正在使用由arekolek制作的Canny egde过滤器的实现 可选:我可以计算得更快吗 最后,我在方法“runEdgeFilter(…)”中编写了所有代码,该方法在我单击设备上的图像时运行,以确保我没有在其他地方干扰imageView。我目前使用的代码Image processing RenderScript';s分配输出返回一个黑色位图,image-processing,allocation,android-bitmap,renderscript,android-renderscript,Image Processing,Allocation,Android Bitmap,Renderscript,Android Renderscript,几天前,我刚刚开始学习RenderScript。我设法创建了一些简单的图像处理过滤器,例如灰度、颜色变化。 现在我正在研究Canny边缘过滤器,但没有成功 问题:为什么ImageView显示黑色图像以及如何解决它? 我正在使用由arekolek制作的Canny egde过滤器的实现 可选:我可以计算得更快吗 最后,我在方法“runEdgeFilter(…)”中编写了所有代码,该方法在我单击设备上的图像时运行,以确保我没有在其他地方干扰imageView。我目前使用的代码 import andro
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v8.renderscript.*;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
private static final float THRESHOLD_MULT_LOW = 0.66f * 0.00390625f;
private static final float THRESHOLD_MULT_HIGH = 1.33f * 0.00390625f;
private ImageView imageView;
private Bitmap img;
private boolean setThresholds = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView);
img = BitmapFactory.decodeResource(getResources(), R.drawable.test_img_no_dpi2);
imageView.setImageBitmap(img);
}
public void imageClicked(View view) {
runEdgeFilter(img, this);
}
private void runEdgeFilter(Bitmap image, Context context) {
int width = image.getWidth();
int height = image.getHeight();
RenderScript rs = RenderScript.create(context);
Allocation allocationIn = Allocation.createFromBitmap(rs, image);
Type.Builder tb;
tb = new Type.Builder(rs, Element.F32(rs)).setX(width).setY(height);
Allocation allocationBlurred = Allocation.createTyped(rs, tb.create());
Allocation allocationMagnitude = Allocation.createTyped(rs, tb.create());
tb = new Type.Builder(rs, Element.I32(rs)).setX(width).setY(height);
Allocation allocationDirection = Allocation.createTyped(rs, tb.create());
Allocation allocationEdge = Allocation.createTyped(rs, tb.create());
tb = new Type.Builder(rs, Element.I32(rs)).setX(256);
Allocation allocationHistogram = Allocation.createTyped(rs, tb.create());
tb = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
Allocation allocationOut = Allocation.createTyped(rs, tb.create());
ScriptC_edge edgeFilter = new ScriptC_edge(rs);
ScriptIntrinsicHistogram histogram = ScriptIntrinsicHistogram.create(rs, Element.U8(rs));
histogram.setOutput(allocationHistogram);
edgeFilter.invoke_set_histogram(allocationHistogram);
edgeFilter.invoke_set_blur_input(allocationIn);
edgeFilter.invoke_set_compute_gradient_input(allocationBlurred);
edgeFilter.invoke_set_suppress_input(allocationMagnitude, allocationDirection);
edgeFilter.invoke_set_hysteresis_input(allocationEdge);
edgeFilter.invoke_set_thresholds(0.2f, 0.6f);
histogram.forEach_Dot(allocationIn);
int[] histogramOutput = new int[256];
allocationHistogram.copyTo(histogramOutput);
if(setThresholds) {
int median = width * height / 2;
for (int i = 0; i < 256; ++i) {
median -= histogramOutput[i];
if (median < 1) {
edgeFilter.invoke_set_thresholds(i * THRESHOLD_MULT_LOW, i * THRESHOLD_MULT_HIGH);
break;
}
}
}
edgeFilter.forEach_blur(allocationBlurred);
edgeFilter.forEach_compute_gradient(allocationMagnitude);
edgeFilter.forEach_suppress(allocationEdge);
edgeFilter.forEach_hysteresis(allocationOut);
allocationOut.copyTo(image);
allocationIn.destroy();
allocationMagnitude.destroy();
allocationBlurred.destroy();
allocationDirection.destroy();
allocationEdge.destroy();
allocationHistogram.destroy();
allocationOut.destroy();
histogram.destroy();
edgeFilter.destroy();
rs.destroy();
imageView.setImageBitmap(image);
}
}
返回白色和黑色像素,因此我认为renderscript可以正常工作。
输出与我以前的renderscript过滤器(uchar4)的类型相同,我成功地将其分配给位图。
我不知道我做错了什么
我的logcat还打印:
V/RenderScript_jni: RS compat mode
V/RenderScript_jni: Unable to load libRSSupportIO.so, USAGE_IO not supported
V/RenderScript_jni: Unable to load BLAS lib, ONLY BNNM will be supported: java.lang.UnsatisfiedLinkError: Couldn't load blasV8 from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.lukasz.edgeexamplers-20.apk,libraryPath=/data/app-lib/com.lukasz.edgeexamplers-20]: findLibrary returned null
E/RenderScript: Couldn't load libRSSupportIO.so
在每个使用renderscript的程序中,但其他程序甚至可以使用此警告
更新#1
正如@Stephen Hines所提到的,阅读越界是有问题的。我想我现在已经通过更改这些行修复了它(没有弄乱renderscript):
edgeFilter.forEach_blur(allocationBlurred);
edgeFilter.forEach_compute_gradient(allocationMagnitude);
edgeFilter.forEach_suppress(allocationEdge);
edgeFilter.forEach_hysteresis(allocationOut);
进入:
但我的问题仍然没有解决。输出和前面一样是黑色的。一个问题是,您的内核中的“x-1”和“x-2”访问显然超出了范围。您需要夹紧到实际图像的边界才能正确地执行此操作。我没有进一步看,因为你没有解释什么是真正不正确的(或者它只是因为边界问题而对你造成了冲击)。您可以尝试打开调试上下文以获得一些帮助()。就警告日志而言,它们确实是无害的。您不需要BLAS或IO支持。谢谢您的评论。使用
RenderScript rs=RenderScript.create(context,RenderScript.ContextType.DEBUG)代码>未在logcat中添加任何新内容。此外,我还强制renderscript处理修剪过的图像,这将消除边界问题。我假设您使用的是单通道输入位图。在这种情况下,您可能应该调用histogram.forEach()而不是histogram.forEach_Dot(),因为后者会将每个像素乘以默认的红点值0.299f。
V/RenderScript_jni: RS compat mode
V/RenderScript_jni: Unable to load libRSSupportIO.so, USAGE_IO not supported
V/RenderScript_jni: Unable to load BLAS lib, ONLY BNNM will be supported: java.lang.UnsatisfiedLinkError: Couldn't load blasV8 from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.lukasz.edgeexamplers-20.apk,libraryPath=/data/app-lib/com.lukasz.edgeexamplers-20]: findLibrary returned null
E/RenderScript: Couldn't load libRSSupportIO.so
edgeFilter.forEach_blur(allocationBlurred);
edgeFilter.forEach_compute_gradient(allocationMagnitude);
edgeFilter.forEach_suppress(allocationEdge);
edgeFilter.forEach_hysteresis(allocationOut);
Script.LaunchOptions sLaunchOpt = new Script.LaunchOptions();
sLaunchOpt.setX(2, width - 3);
sLaunchOpt.setY(2, height - 3);
edgeFilter.forEach_blur(allocationBlurred, sLaunchOpt);
edgeFilter.forEach_compute_gradient(allocationMagnitude, sLaunchOpt);
edgeFilter.forEach_suppress(allocationEdge, sLaunchOpt);
edgeFilter.forEach_hysteresis(allocationOut, sLaunchOpt);