我的图像中包含许多消除锯齿的线条,并尝试删除低于某个Alpha通道阈值的像素(高于阈值的任何内容都会转换为完整的255 alpha)。我已经对它进行了编码和工作,它只是没有在大图像上运行它时的速度。有没有人有他们建议的替代方法?
//This will convert all pixels with > minAlpha to 255
public static void flattenImage(BufferedImage inSrcImg, int minAlpha)
{
//loop through all the pixels in the image
for (int y = 0; y < inSrcImg.getHeight(); y++)
{
for (int x = 0; x < inSrcImg.getWidth(); x++)
{
//get the current pixel (with alpha channel)
Color c = new Color(inSrcImg.getRGB(x,y), true);
//if the alpha value is above the threshold, convert it to full 255
if(c.getAlpha() >= minAlpha)
{
inSrcImg.setRGB(x,y, new Color(c.getRed(), c.getGreen(), c.getBlue(), 255).getRGB());
}
//otherwise set it to 0
else
{
inSrcImg.setRGB(x,y, new Color(0,0,0,0).getRGB()); //white (transparent)
}
}
}
}
根据@BenoitCoudour的评论我已经相应地修改了代码,但它似乎影响了像素的RGB值,任何想法我可能做错了什么?
public static void flattenImage(BufferedImage src, int minAlpha)
{
int w = src.getWidth();
int h = src.getHeight();
int[] rgbArray = src.getRGB(0, 0, w, h, null, 0, w);
for (int i=0; i<w*h; i++)
{
int a = (rgbArray[i] >> 24) & 0xff;
int r = (rgbArray[i] >> 16) & 0xff;
int b = (rgbArray[i] >> 8) & 0xff;
int g = rgbArray[i] & 0xff;
if(a >= minAlpha) { rgbArray[i] = (255<<24) | (r<<16) | (g<<8) | b; }
else { rgbArray[i] = (0<<24) | (r<<16) | (g<<8) | b; }
}
src.setRGB(0, 0, w, h, rgbArray, 0, w);
}
答案 0 :(得分:1)
可能减慢你速度的是每个像素的Color对象的实例化。 请参阅此答案以迭代BufferedImage中的像素并访问Alpha通道:https://stackoverflow.com/a/6176783/3721907
我只是粘贴下面的代码
public Image alpha2gray(BufferedImage src) { if (src.getType() != BufferedImage.TYPE_INT_ARGB) throw new RuntimeException("Wrong image type."); int w = src.getWidth(); int h = src.getHeight(); int[] srcBuffer = src.getData().getPixels(0, 0, w, h, null); int[] dstBuffer = new int[w * h]; for (int i=0; i<w*h; i++) { int a = (srcBuffer[i] >> 24) & 0xff; dstBuffer[i] = a | a << 8 | a << 16; } return Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(w, h, pix, 0, w)); }
这非常接近你想要达到的目标。
答案 1 :(得分:0)
您的理论复杂度为O(n)
,您可以通过执行字节操作来优化它。
你可以进一步使用线程(你有一个令人尴尬的并行问题),但由于大多数用户机器最多有8个物理线程,所以它不会让你太过分。您可以通过一次操作图像的一部分来添加另一级优化,适应系统中的内存缓冲区和不同的缓存级别。
由于我已经提到过你有一个令人尴尬的并行问题,最好的解决方案是执行GPU编程。
您可以在simple image processing with cuda上关注本教程,并将过滤器的代码更改为此类
void blur(unsigned char* input_image, unsigned char* output_image, int width, int height) {
const unsigned int offset = blockIdx.x*blockDim.x + threadIdx.x;
const int currentoffset = (offset)*4;
if(offset < width*height) {
if (input_image[currentoffset+3]>= threshold )
output_red = input_image[currentoffset];
output_green = input_image[currentoffset+1];
output_blue = input_image[currentoffset+2];
output_alpha = 255;
}else{
output_red = 0;
output_green = 0;
output_blue = 0;
output_alpha = 0;
}
}
}
output_image[currentoffset*3] = output_red;
output_image[currentoffset*3+1] = output_green;
output_image[currentoffset*3+2] = output_blue;
output_image[currentoffset*3+3] = output_alpha
}
}
如果您已开始使用Java,那么您可以在这里找到关于如何开始使用using java with nvidia gpu
的绝佳答案