読者です 読者をやめる 読者になる 読者になる

(O+P)ut

IT系の記事やその他諸々,不定期で更新していきます(∵)

【Java】簡単モザイク生成

Java テクノロジー

これはなんのキャラクターでしょうか。
f:id:mtiit:20170314232445j:plain
どことなく、国民的アニメの主人公に色合いが似てる気がしませんか?

少し前に、モザイクをかけても人間はアニメキャラクターを見破ってしまう というのが話題になりました。
私も同じように、画像を配列と見た時に各行の平均の色を出力することで簡易モザイクを作成する遊びをしてみたのでここに共有します。

Javaでの画像取得は以下のように行います。BurreredImageのメソッドを用いて縦横のサイズも取得可能。

File f = new File("[入力画像のフルパス]");
BufferedImage read=ImageIO.read(f);
int w = read.getWidth();
int h = read.getHeight();

さて、画像の各画素を取り出して平均をとりたいんですが、
BufferedImageでは画素を取得するメソッドgetRGBを用いると、 R G B を8bitずつで表現する以下のような形が返り値となっています。
00000000 00000000 00000000 00000000
なので、R G B をそれぞれ取り出すために

public class Img{
 public static int r(int c){
  return c>>16&0xff;
 }
 public static int g(int c){
  return c>>8&0xff;
 }
 public static int b(int c){
  return c&0xff;
 }
 public static int rgb(int r,int g,int b){
  return 0xff000000 | r <<16 | g <<8 | b;
 }
}

といったクラスを用意しておくと便利ですね。
rgbは、各r,g,bを基に元の値を構成するメソッドです。

画像の各列の画素の平均値の画像を出力するコードは以下になります。

public class Main {
 public static void main(String[] args) throws IOException {
  File f = new File("[入力画像のフルパス]");
  BufferedImage read=ImageIO.read(f);
  int w = read.getWidth();
  int h = read.getHeight();
  BufferedImage write = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
  for(int y=0;y<h;y++){
   int r = 0;
   int g = 0;
   int b = 0;
   for(int x=0;x<w;x++){
    int c = read.getRGB(x,y);
    r = r + Img.r(c);
    g = g + Img.g(c);
    b = b + Img.b(c);
   }
   int n_r = r/h;
   int n_g = g/h;
   int n_b = b/h;
   for(int xx=0;xx<w;xx++){
    int rgb = Img.rgb(n_r, n_g, n_b);
    write.setRGB(xx, y, rgb);
   }
  }
  File f2 = new File("[出力先のフルパス]");
  ImageIO.write(write, "jpg", f2); //jpgで出力
 }
}

最初に見せたモザイク画像の元画像はこちらです。
f:id:mtiit:20170314234708p:plain
両側が黒くなっているのは、透明化している部分の画素が 0/0/0 で 黒と同じだからみたいです。
この辺は、改良の余地ありですね。以上です。