Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to blur a portion of an image with JAVA

How to blur a portion of an image, to hide some privates parts like credit card informations.

I try to use ConvolveOp.class like :

float[] matrix = new float[400];
for (int i = 0; i < 400; i++)
    matrix[i] = 1.0f/500.0f;

BufferedImage sourceImage =  (BufferedImage) image; ;
BufferedImage destImage = null ;
BufferedImageOp op = new ConvolveOp( new Kernel(20, 20, matrix), ConvolveOp.EDGE_NO_OP, null );
BufferedImage blurredImage = op.filter(sourceImage, destImage);

it seems to work, except that the image is completely blurred.

like image 351
Karim Oukara Avatar asked Jul 27 '15 09:07

Karim Oukara


2 Answers

In the case you want to focus on the application and not on the specifics of image processing, you can use an image processing framework like Marvin. Thus, you can do more with less code.

Input image:

enter image description here

Output image:

enter image description here

Source code:

import static marvin.MarvinPluginCollection.*;

public class PortionBlur {
    public PortionBlur(){
        // 1. Load image
        MarvinImage image = MarvinImageIO.loadImage("./res/credit_card.jpg");

        // 2. Create masks for each blurred region
        MarvinImageMask mask1 = new MarvinImageMask(image.getWidth(), image.getHeight(), 38,170,345,24);
        MarvinImageMask mask2 = new MarvinImageMask(image.getWidth(), image.getHeight(), 52,212,65,24);
        MarvinImageMask mask3 = new MarvinImageMask(image.getWidth(), image.getHeight(), 196,212,65,20);
        MarvinImageMask mask4 = new MarvinImageMask(image.getWidth(), image.getHeight(), 38,240,200,20);

        // 3. Process Image with each mask
        GaussianBlur gaussianBlur = new GaussianBlur();
        gaussianBlur.load();
        gaussianBlur.attributes.set("radius",15);

        gaussianBlur.process(image.clone(), image, mask1);
        gaussianBlur.process(image.clone(), image, mask2);
        gaussianBlur.process(image.clone(), image, mask3);
        gaussianBlur.process(image.clone(), image, mask4);

        // 4. Save the final image
        MarvinImageIO.saveImage(image, "./res/credit_card_out.jpg");
    }
    public static void main(String[] args) {
        new PortionBlur();
        System.exit(0);
    }
}

Gaussian blur algorithm source code:

https://github.com/gabrielarchanjo/marvinproject/blob/master/marvinproject/dev/MarvinPlugins/src/org/marvinproject/image/blur/gaussianBlur/GaussianBlur.java

like image 154
Gabriel Ambrósio Archanjo Avatar answered Oct 26 '22 02:10

Gabriel Ambrósio Archanjo


I don't know whether this can be done by changing the matrix values, but this should definitely be possible by filtering a subimage, since, according to the BufferedImage.getSubimage() documentation:

The returned BufferedImage shares the same data array as the original image.

So the original BufferedImage should change with code like this:

BufferedImage image = /* ... */;
BufferedImage subImage = image.getSubimage(10, 20, 30, 40); // x, y, width, height
new ConvolveOp(new Kernel(20, 20, matrix), ConvolveOp.EDGE_NO_OP, null).filter(subImage, subImage);

I didn't test this though, and I can imagine that filter doesn't work as expected if source and destination are the same, in which case you could use a copy of the subimage, using the solution from this question:

BufferedImage image = /* ... */;
BufferedImage dest = image.getSubimage(10, 20, 30, 40);  // x, y, width, height
ColorModel cm = dest.getColorModel();
BufferedImage src = new BufferedImage(cm, dest.copyData(dest.getRaster().createCompatibleWritableRaster()), cm.isAlphaPremultiplied(), null).getSubimage(0, 0, dest.getWidth(), dest.getHeight());
new ConvolveOp(new Kernel(20, 20, matrix), ConvolveOp.EDGE_NO_OP, null).filter(src, dest);

After that, continue working with image (not subImage, src or dest!)

like image 42
Siguza Avatar answered Oct 26 '22 03:10

Siguza