-
-
Save Brixomatic/e0961c41219a82aeed3a175c1385f9df to your computer and use it in GitHub Desktop.
Haar transform
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package haar; | |
import java.awt.*; | |
import java.awt.image.*; | |
import java.io.IOException; | |
import javax.imageio.ImageIO; | |
import javax.swing.*; | |
import haar.RGBChannelFilter.Channel; | |
public class App { | |
public static void main(final String[] args) { | |
try { | |
final HaarTransform haarTransform = new HaarTransform(); | |
final BufferedImage image = ImageIO.read(App.class.getResourceAsStream("Geisha-by-Luca-Tarlazzi-513x640.jpg")); | |
System.out.println(new Dimension(image.getWidth(), image.getHeight())); | |
final Image grayScale = convertToGrayScale(image); | |
final BufferedImage bufferedImage = toBufferedImage(grayScale); | |
displayImage(bufferedImage); | |
final double[][] result = haarTransform.transform(imageToMatrix(bufferedImage)); | |
final BufferedImage updated = toImage(result); | |
displayImage(updated); | |
} catch (final IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
private static void displayImage(final Image image) { | |
EventQueue.invokeLater(new Runnable() { | |
@Override | |
public void run() { | |
final JLabel lblimage = new JLabel(new ImageIcon(image)); | |
final JFrame frame = new JFrame(); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.getContentPane().add(lblimage, BorderLayout.CENTER); | |
frame.pack(); | |
frame.setVisible(true); | |
final JPanel mainPanel = new JPanel(new BorderLayout()); | |
mainPanel.add(lblimage); | |
frame.add(mainPanel); | |
frame.setVisible(true); | |
} | |
}); | |
} | |
private static Image convertToGrayScale(final BufferedImage colorImage) { | |
final ImageFilter filter = new RGBChannelFilter(Channel.Red); | |
final ImageProducer producer = new FilteredImageSource(colorImage.getSource(), filter); | |
return Toolkit.getDefaultToolkit().createImage(producer); | |
} | |
private static BufferedImage toBufferedImage(final Image img) { | |
if (img instanceof BufferedImage) { | |
return (BufferedImage) img; | |
} | |
final BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); | |
final Graphics2D bGr = bimage.createGraphics(); | |
bGr.drawImage(img, 0, 0, null); | |
bGr.dispose(); | |
return bimage; | |
} | |
private static double[][] imageToMatrix(final BufferedImage image) { | |
final Dimension dim = new Dimension(image.getWidth() / 2 * 2, image.getHeight() / 2 * 2); // dimension must be even | |
final double[][] matrix = new double[dim.width][dim.height]; | |
for (int y = 0; y < dim.height; y++) { // height must be even | |
for (int x = 0; x < dim.width; x++) { // width must be even | |
matrix[x][y] = getPixel(image, x, y); | |
} | |
} | |
return matrix; | |
} | |
private static int getPixel(final BufferedImage image, final int x, final int y) { | |
final int clr = image.getRGB(x, y); | |
return clr & 0x000000ff; | |
} | |
private static BufferedImage toImage(final double[][] transform) { | |
final Dimension dim = new Dimension(transform.length, transform[0].length); // dimension must be even | |
final BufferedImage image = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_RGB); | |
for (int y = 0; y < dim.height; ++y) { | |
for (int x = 0; x < dim.width; ++x) { | |
int value = (int) transform[x][y]; | |
value = value < 0 ? 255 + value : value; | |
final Color color = new Color(value, value, value); | |
image.setRGB(x, y, color.getRGB()); | |
} | |
} | |
return image; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package haar; | |
public class HaarTransform { | |
public double[][] transform(final double[][] input) { | |
return transformRows(transformColumns(input)); | |
} | |
private static double[][] transformColumns(final double[][] input) { | |
final int width = input.length; | |
final int height = input[0].length; | |
final double[][] result = new double[width][height]; | |
for (int y = 0; y < height; ++y) { | |
for (int x = 0; x < width / 2; ++x) { | |
result[x][y] = (input[2 * x][y] + input[2 * x + 1][y]) / 2.0; | |
result[width / 2 + x][y] = (input[2 * x][y] - input[2 * x + 1][y]) / 2.0; | |
} | |
} | |
return result; | |
} | |
private static double[][] transformRows(final double[][] input) { | |
final int width = input.length; | |
final int height = input[0].length; | |
final double[][] result = new double[width][height]; | |
for (int x = 0; x < width; ++x) { | |
for (int y = 0; y < height / 2; ++y) { | |
result[x][y] = (input[x][2 * y] + input[x][2 * y + 1]) / 2.0; | |
result[x][height / 2 + y] = (input[x][2 * y] - input[x][2 * y + 1]) / 2.0; | |
} | |
} | |
return result; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package haar; | |
import java.awt.Color; | |
import java.awt.image.RGBImageFilter; | |
/** | |
* @author Wanja Gayk | |
*/ | |
public class RGBChannelFilter extends RGBImageFilter { | |
private final Channel channel; | |
public static enum Channel { | |
Alpha { | |
@Override | |
int extract(final int rgb) { | |
return rgb >> 24 & 0xFF; | |
} | |
}, | |
Red { | |
@Override | |
int extract(final int rgb) { | |
return rgb >> 16 & 0xFF; | |
} | |
}, | |
Green { | |
@Override | |
int extract(final int rgb) { | |
return rgb >> 8 & 0xFF; | |
} | |
}, | |
Blue { | |
@Override | |
int extract(final int rgb) { | |
return rgb & 0xFF; | |
} | |
}; | |
abstract int extract(final int rgb); | |
}; | |
public RGBChannelFilter(final Channel channel) { | |
// canFilterIndexColorModel indicates whether or not it is acceptable | |
// to apply the color filtering of the filterRGB method to the color | |
// table entries of an IndexColorModel object in lieu of pixel by pixel | |
// filtering. | |
canFilterIndexColorModel = true; | |
this.channel = channel; | |
} | |
@SuppressWarnings("unused") | |
@Override | |
public int filterRGB(final int x, final int y, final int rgb) { | |
final int channelValue = channel.extract(rgb); | |
return new Color(channelValue, channelValue, channelValue).getRGB(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Changes: