Android 如何使用一个像素的Sobel矩阵
我想在我的android应用程序中使用Android 如何使用一个像素的Sobel矩阵,android,image-processing,Android,Image Processing,我想在我的android应用程序中使用Sobel操作符。但我不明白如何使用一个像素 int sobel_x[][] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}; int sobel_y[][] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}; Bitmap source = ImageHelper.GetBitmapGromUri(Path); int w =
Sobel
操作符。但我不明白如何使用一个像素
int sobel_x[][] = {{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}};
int sobel_y[][] = {{-1, -2, -1},
{0, 0, 0},
{1, 2, 1}};
Bitmap source = ImageHelper.GetBitmapGromUri(Path);
int w = source.getWidth();
int h = source.getHeight();
int[] pixels;
pixels = new int[h * w];
source.getPixels(pixels, 0, w, 1, 1, w - 1, h - 1);
for(int i = 0;i < pixels.length;i++){
...
}
intsobel_x[][]={{-1,0,1},
{-2, 0, 2},
{-1, 0, 1}};
int sobel_y[][]={{-1,-2,-1},
{0, 0, 0},
{1, 2, 1}};
位图源=ImageHelper.GetBitmapGromUri(路径);
int w=source.getWidth();
int h=source.getHeight();
int[]像素;
像素=新整数[h*w];
getPixels(像素,0,w,1,1,w-1,h-1);
对于(int i=0;i
我尝试使用
get/setPixel
。但是速度非常慢。单个像素访问绝对不是正确的方式
我假设您已经将源转换为灰度,所以它本质上是一个字节数组。我建议您使用类似以下的方法来提取数据:
int w = source.getWidth();
int h = source.getHeight();
ByteBuffer buffer = ByteBuffer.allocate( w * h );
source.copyPixelsToBuffer( buffer );
final byte[] bitmapData = buffer.array()
这将为您提供源数据。现在,您可以对其应用Sobel过滤器。请注意,您希望将生成的输出字节写入一个新的byte
数组,然后将其转换回图像
byte[] output = new byte[ w * h ];
for( int y=1; y<h-1; y++ ) {
for( int x=1; x<w-1; x++ ) {
int idx = y * w + x;
// Apply Sobel filter
byte sx = (byte) ((-1 * bitmapData[idx-w-1]) + ( 1 * bitmapData[idx-w+1] ) + (-2 * bitmapData[idx-1]) + ( 2 * bitmapData[idx+1] ) + (-1 * bitmapData[idx+w-1]) + ( 1 * bitmapData[idx+w+1] ) );
output[idx] = sx;
}
}
byte[]输出=新字节[w*h];
对于(inty=1;y好消息和坏消息。以下方法有效,但
由于某种特殊的原因,Android不允许您创建8位灰度图像。这意味着您必须创建ARGB_8888格式的灰度图像。这可能是您以前版本中出现的问题,我们将数据读取为字节,而不是字节
下面的代码可以正常工作,我只在模拟器上运行过你的图像,速度慢得离谱(11秒)。当然,你的图像很大,但我猜,这仍然是一种缓慢的方式
我强烈建议考虑使用OpenCV Java库,因为它们与Android位图类不同,既快速又节省内存
public class Sobel {
private static Bitmap toGreyScale( Bitmap source ) {
Bitmap greyScaleBitmap = Bitmap.createBitmap(
source.getWidth(), source.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(greyScaleBitmap);
Paint p = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(cm);
p.setColorFilter(filter);
c.drawBitmap(source, 0, 0, p);
return greyScaleBitmap;
}
public static void doSobel( Bitmap source) {
Bitmap grey = toGreyScale(source);
int w = grey.getWidth();
int h = grey.getHeight();
// Allocate 4 times as much data as is necessary because Android.
int sz = w * h;
IntBuffer buffer = IntBuffer.allocate( sz );
grey.copyPixelsToBuffer( buffer );
final int[] bitmapData = buffer.array();
int[] output = new int[ w * h ];
for( int y=1; y<h-1; y++ ) {
for( int x=1; x<w-1; x++ ) {
int idx = (y * w + x );
// Apply Sobel filter
int tl = (bitmapData[idx - w - 1]) & 0xFF;
int tr = (bitmapData[idx - w + 1]) & 0xFF;
int l = (bitmapData[idx - 1]) & 0xFF;
int r = (bitmapData[idx + 1]) & 0xFF;
int bl = (bitmapData[idx + w - 1]) & 0xFF;
int br = (bitmapData[idx + w + 1]) & 0xFF;
int sx = (int) ( tr - tl + 2 * ( r - l ) + br - bl );
sx = sx & 0xFF;
// Put back into ARG and B bytes
output[toIdx] = (sx << 24) | ( sx << 16) | (sx << 8) | sx;
}
}
source.copyPixelsFromBuffer( IntBuffer.wrap(output));
}
}
公共类Sobel{
专用静态位图toGreyScale(位图源){
位图灰度缩放位图=位图.createBitmap(
source.getWidth(),source.getHeight(),
位图.Config.ARGB_8888);
画布c=新画布(灰色缩放位图);
油漆p=新油漆();
ColorMatrix cm=新的ColorMatrix();
cm.设定饱和度(0);
ColorMatrixColorFilter过滤器=新的ColorMatrixColorFilter(厘米);
p、 设置彩色滤光片(滤光片);
c、 drawBitmap(源,0,0,p);
返回灰度刻度位图;
}
公共静态void doSobel(位图源){
位图灰色=toGreyScale(源);
int w=grey.getWidth();
inth=grey.getHeight();
//分配4倍于所需的数据,因为Android。
int sz=w*h;
IntBuffer=IntBuffer.allocate(sz);
灰色。copyPixelsToBuffer(缓冲区);
final int[]bitmapData=buffer.array();
int[]输出=新的int[w*h];
对于(int y=1;yint[]输出=新字节[w*h];
-错误。如果使用int数组。如何设置为结果?result.setPixels(输出,0,w,h);
??如果字节数组-结果。copyPixelsFromBuffer(输出);
@NickDevil将输出设置为int[],并使用Bitmap.createBitmap(int[]颜色、整数偏移量、整数步长、整数宽度、整数高度、位图.Config)或类似设置。或者将输出设为字节[],并使用copyPixelsFromBuffer()
它工作正常,但结果不好,@NickDevil您需要确保位图类型与您使用的源数据相同。例如,为您使用的数据类型适当设置配置、跨距、偏移量等。位图res=Bitmap.createBitmap(输出,0,w,w,h,source.getConfig())我用这个。是的。它工作。在我的手机里-0秒。但是toIdx
==idx
?结果不好:(