Adam
Adam

Reputation: 603

Code for image convolution not displaying an image properly?

So heres the deal: I tried simplifiying (to the user) how to execute convolution. I tried using this to run a Sobel filter and when i try to display the image (via jfram and image icon) the image icon doesnt pop up, it just a big gray square.

The jframe/imageicon worked flawlessly until i tried to get it to display the output of the result of this filter.

    float[][] sobel = { { -1, 0, 1},
                   { -2, 0, 2},
                   {-1, 0, 1} };
someObject test = new someObject(filepath);
test.convolutionFilter(sobel);

public BufferedImage convolutionFilter(float[][] filter) {
    int columns = filter.length;
    int  rows= filter[0].length;
    float numTemp;
    float[] filter1D = new float[columns*rows];
    for (int j = 0; j<rows; j++) {
        for (int i= 0; i< columns; i++ ) {
            numTemp = filter[j][i];
            System.out.print(numTemp + " ");
            filter1D[j*columns + i] = numTemp;
        }
    }


    Kernel kern = new Kernel(rows, columns, filter1D);
    ConvolveOp op = new ConvolveOp(kern);

    BufferedImage temp = new BufferedImage(processedImage.getWidth(), processedImage.getHeight(), BufferedImage.TYPE_INT_ARGB); 
    op.filter(processedImage, temp);
    processedImage = temp;
    return processedImage;

}

CODE HAS BEEN UPDATED

If i do the following my gui will display a plane gray frame with no image. If I do one command and not the other, the image will display perfectly. BufferedImage testImage = ImageIO.read(filepath);

float[][] sobelFilter = { { -1, 0, 1}, 
                  { -2, 0, 2}, 
                  { -1, 0, 1} }; 
testImage = SimpleImage.toGrayscale(testImage); 
testImage =  SimpleImage.convolutionFilter(testImage, sobelFilter); 
//use some swing functions to display image 

if I JUST convert to grayscale I will get correct results, if i just apply JUST the filter I will get correct results. If I Complete this AS IS I get a Blank GUI screen that popsup. If I swap the order that they are executed (filter first then convert to grayscale) I will get results.

I think something with the grayscale conversion process is screwing up the convolution

toGrayscale should convert the image to grayscale

convolutionFilter should take a 2D image filter, unroll it into 1D array and then convolve the processedImage and return the result.

public class SimpleImage { 
public static BufferedImage toGrayscale(BufferedImage processedImage) { 
     BufferedImage tempImage = new BufferedImage(processedImage.getWidth(), processedImage.getHeight(), processedImage.getType()); 
     BufferedImageOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);  
     tempImage = op.filter(processedImage, null);  
     return tempImage; 
}   


public static BufferedImage convolutionFilter(BufferedImage processedImage, float[][] filter2D) {     
    BufferedImage tempImage = new BufferedImage(processedImage.getWidth(), processedImage.getHeight(), processedImage.getType()); 
    int columns = filter2D.length; 
    int  rows= filter2D[0].length; 
    //Unrolls a 2D filter into a 1D filter 
    float[] filter1D = new float[columns*rows]; 
    for (int j = 0; j<rows; j++) { 
            for (int i= 0; i< columns; i++ ) { 
            filter1D[j*columns + i] = filter2D[j][i]; 
        } 
    } 
    //creates Kernal and convolution operator 
    Kernel kern = new Kernel(rows, columns, filter1D); 
    ConvolveOp op = new ConvolveOp(kern); 
    //apply filtering  
    tempImage = op.filter(processedImage, null); 
    return tempImage; 

    } 
 } 

Upvotes: 1

Views: 2060

Answers (1)

tenorsax
tenorsax

Reputation: 21223

Not sure what is your input image, so may be there is a discrepancy in the imageType (BufferedImage.TYPE_INT_ARGB) argument that you specify for you temp image constructor. You don't have to provide a destination image in:

op.filter(processedImage, temp);

You can use the image returned by ConvolveOp.filter(), try the following:

public BufferedImage convolutionFilter(float[][] filter, BufferedImage processedImage) {
...
Kernel kern = new Kernel(rows, columns, filter1D);
ConvolveOp op = new ConvolveOp(kern);
BufferedImage temp = op.filter( processedImage, null );
return temp;
}

Then the resulting image will created with the source ColorModel.

EDIT after toGrayscale() introduction

I could not reproduce the problem you're having with toGrayScale/convolutionFilter combination. I am getting correct results using both of your updated methods. Any chance you can share the image you're using?

EDIT :

This code works for the mentioned image:

public static void main(String args[]) {
    try {
        BufferedImage image = ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png"));
        image = SimpleImage.toGrayscale(image);
        image = SimpleImage.convolutionFilter(image, sobel);
        JOptionPane.showMessageDialog(null, "", "", JOptionPane.INFORMATION_MESSAGE, new ImageIcon( image ));
    } catch (Exception e) {
        JOptionPane.showMessageDialog(null, e.getMessage(), "Failure", JOptionPane.ERROR_MESSAGE);
        e.printStackTrace();
    } 
  } 

Also, note that the type of mentioned image is TYPE_3BYTE_BGR. This can interfere with proper operation of ConvolveOp. Here is a bug. Looks like it was fixed only in Java 7.

Also, note that initial allocation of tempImage in your implementation of toGrayscale() and convolutionFilter() is redundant.

Upvotes: 3

Related Questions