0

Edit: I included an example of k value. Also to be clear I produce three separate arrays from an RGB image . I also include code for loading the image

public static final int[][] SHARPEN = { { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } };

Load image

BufferedImage inputImage = ImageIO.read(new File("bridge-rgb.png")); // load the image from this current folder

When I convolute an image in java using 3*3 kernel, the resultant image produced has some of the properties that you would expect from the given kernel but is extremely dark, black being the dominant colour. If I process the image with an identity kernel then identity is returned so I guess that means that Ive selected the correct setting for creating a bufferedImage and hence the problem must be with my convolution algorithm, however I did test the convolution algorithm with a test array and it does seem to be producing accurate output. I wonder could any one make any comment on what I have or point me in the right direction?

for (int j = 0; j < kernelWidth; ++j) {

    try {  
      output+=(input[y-1][x-1+j] * k[0][j]);
      counter++;
    }catch(Exception e) {
        continue;
    }
       }  
          for (int j = 0; j < kernelWidth;++j) {
      try {
      output+=(input[y][x-1+j] * k[1][j]);
      counter1++;
      }catch(Exception e) {
            continue;
        }
      } 
      
          for (int j = 0; j < kernelWidth;++j) {
      try {
      output+=(input[y+1][x-1+j] * k[2][j]);
      counter2++;
      }catch(Exception e) {
            continue;
        }
      } 
 

 if((output>>bitshiftValue)>255) { 
         return ((255& 0xff)<<bitshiftValue);
     }
    
      else if ((output>>bitshiftValue)<0) {
      
     return 0;
     }else {
 

return  output;
      }  }   

I got the arrays to be convoluted with the following method

          private static int[][] convertTo2DWithoutUsingGetRGBgreen(BufferedImage image) {

    final byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
    final int width = image.getWidth();
    final int height = image.getHeight();
    

    int[][] result = new int[height][width];
    
    final int pixelLength = 4;
    for (int pixel = 0, row = 0, col = 0; pixel + 3 < pixels.length; pixel += pixelLength) {
        result[row][col] = ((int) ((pixels[pixel + 2] & 0xff) )<<8);

        col++;
        if (col == width) {
            col = 0;
            row++;
        }

    }

    return result;
}

and post convolution I pimply added them together like so

          int[][] finalConv = new int[convRedArray.length][convRedArray[0].length];
 for(int c =0; c<convRedArray.length;c++) {
    for(int p =0;p<convRedArray[0].length;p++) {
        finalConv[c][p]=(convBlueArray[c][p])+(convGreenArray[c[p])+(convRedArray[c][p]);                                                                               
  
Ciaran
  • 23
  • 6
  • What values and types are `k` and `bitshiftValue`? I recommend that you just use a regular division rather than trying to use bit shifts. That division is not going to be a bottleneck in your code, and it will avoid all sorts of bugs (I suspect it's the reason for your bug here). – Cris Luengo Jun 07 '21 at 15:03
  • K , int [][] /convolution kernel. Bitshift int value , 16 for red and 8 for green. If I was to do regular division that would be dividing the output by the max and min decimal values of the colours range in the 32 bit RGB number, eg for blue that would be 1 to 255 ?? I don't really understand. – Ciaran Jun 07 '21 at 15:15
  • Shifting right by 16 bits is the same as dividing by 65,536. Do the values in your `k` add up to that number? I am sure they don't. Your output is too dark because you divide by a value that is too large. – Cris Luengo Jun 07 '21 at 15:17
  • 1
    Typical the kernel adds up to 1 . – Ciaran Jun 07 '21 at 15:20
  • When I bitshift the value they come up in the range 0 - 255 – Ciaran Jun 07 '21 at 15:21
  • What values does your `k` have when you set `bitshiftValue=16`? Please [edit] this information into your question. See [mre]. – Cris Luengo Jun 07 '21 at 15:24
  • I tried to add extra information, my (probably flawed )understanding is that I left shifted the raster pixels to get them in to the int RGB format, and then i right shifted them in the same fashion to compare them with the range 0 -255. – Ciaran Jun 07 '21 at 15:47
  • I see what you were saying , the value of k is quite small but the values of the input array, representing an image , are quite large especially on the red channel. – Ciaran Jun 07 '21 at 16:23
  • OK, so the bit shifting is to convert a 24-bit RGB value to individual 8-bit values? It seems weird, with the way you use it. Shouldn't you be bit shifting and masking the input values instead? – Cris Luengo Jun 07 '21 at 17:00
  • Your example value for `k` is the Sobel approximation to a derivative filter (you call it `SHARPEN`, though it's not a sharpening filter). The result of this filter will have both negative and positive values. You set all negative values to 0, but this is, on average, half the output values. If you want to work with derivatives, you need a signed type for your output, and you need to preserve those negative values. Alternatively, you could add 128, then clip to the 0-255 range. – Cris Luengo Jun 07 '21 at 17:01
  • I mask the individual RGB pixels in the method convertTo2DWithoutUsingGetRGBgreen() and then I perform convolution on individual RGB arrays. Though I don't know if this is the correct approach. – Ciaran Jun 07 '21 at 18:07

0 Answers0