문제

나는 Java와 함께 제공되는 내장 연산자를 사용하는 대신 나만의 컨볼루션 연산자를 만들려고 노력해 왔습니다.이 이미지에 내장된 컨볼루션 연산자를 적용했습니다.링크

내장된 컨볼루션 연산자와 가우스 필터를 사용하여 이 이미지를 얻었습니다.링크

이제 내 코드를 사용하여 동일한 이미지를 실행합니다.

public static int convolve(BufferedImage a,int x,int y){
 int red=0,green=0,blue=0;
      float[] matrix = { 
 0.1710991401561097f, 0.2196956447338621f, 0.1710991401561097f, 
 0.2196956447338621f, 0.28209479177387814f, 0.2196956447338621f, 
 0.1710991401561097f, 0.2196956447338621f, 0.1710991401561097f, 
 };
      for(int i = x;i<x+3;i++){
          for(int j = y;j<y+3;j++){
              int color = a.getRGB(i,j);
              red += Math.round(((color >> 16) & 0xff)*matrix[(i-x)*3+j-y]);
              green += Math.round(((color >> 8) & 0xff)*matrix[(i-x)*3+j-y]);
              blue += Math.round(((color >> 0) & 0xff)*matrix[(i-x)*3+j-y]);

          }
      }

    return (a.getRGB(x, y)&0xFF000000) | (red << 16) | (green << 8) | (blue);
}

그리고 제가 얻은 결과는 이것입니다.링크

또한 내가 작성한 코드를 어떻게 최적화합니까?내장된 컨볼루션 연산자는 1~2초가 걸리는 반면 내 코드는 예상한 대로 정확한 목적을 제공하지 않더라도 5~7초가 걸립니다!

업로드하는 동안 실수로 소스 이미지를 회전시켰습니다.그러니 무시해 주세요.

도움이 되었습니까?

해결책

우선, 루프의 각 주기에서 결과를 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에 익숙하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top