우선, 루프의 각 주기에서 결과를 float에서 int로 불필요하게(그리고 잘못) 변환하고 있습니다.당신의 red
, green
그리고 blue
float 유형이어야 하며 컨볼루션 후에만 정수로 다시 캐스팅되어야 합니다(RGB로 다시 변환하는 경우).
float red=0.0f, green = 0.0f, blue = 0.0f
for(int i = x;i<x+3;i++){
for(int j = y;j<y+3;j++){
int color = a.getRGB(i,j);
red += ((color >> 16) & 0xff)*matrix[(i-x)*3+j-y];
green += ((color >> 8) & 0xff)*matrix[(i-x)*3+j-y];
blue += ((color >> 0) & 0xff)*matrix[(i-x)*3+j-y];
}
}
return (a.getRGB(x, y)&0xFF000000) | (((int)red) << 16) | (((int)green) << 8) | ((int)blue);
결과에서 색상 번짐은 다음의 계수로 인해 발생합니다. matrix
틀렸어요:
0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f + 0.2196956447338621f + 0.28209479177387814f + 0.2196956447338621f + 0.1710991401561097f + 0.2196956447338621f + 0.1710991401561097f = 1.8452741
블러링 컨볼루션 행렬의 계수 합은 1.0이어야 합니다.이 매트릭스를 이미지에 적용하면 255가 넘는 색상을 얻을 수 있습니다.그런 일이 발생하면 채널이 다음 채널로 "번져나갑니다"(파란색에서 녹색으로 등).이 매트릭스가 포함된 완전히 녹색 이미지의 결과는 다음과 같습니다.
green = 255 * 1.8452741 ~= 471 = 0x01D7; rgb = 0xFF01D700;
약간 빨간색이 가미된 덜 강렬한 녹색입니다.
계수를 다음과 같이 나누어서 문제를 해결할 수 있습니다. 1.8452741
, 하지만 다음 사항을 확인하고 싶습니다.
(int)(255.0f * (sum of coefficients)) = 255
그렇지 않은 경우 채널 크기를 255로 제한하고 둘러싸지 않도록 하는 검사를 추가해야 합니다.예:
if (red > 255.0f)
red = 255.0f;
효율성/최적화 관련:
이러한 불필요한 캐스팅 및 Math.Round 호출로 인해 속도 차이가 설명될 수도 있지만, 이미지에 액세스하는 방식이 더 가능성이 높습니다.나는 기본 이미지 버퍼에 액세스하는 가장 효율적인 방법에 대해 조언할 만큼 BufferedImage 및 Raster에 익숙하지 않습니다.