PHPで上司に猫耳つけるロジック書いたからここに記す


## 前提
シャチクソンで、むかつく上司に猫耳つけて和もう！ってことで上司に猫耳つけるロジックを書く担当になり、無事で来たのでここに記します。

## 条件
画像アップロードは他の方が担当し、アップロードされたファイル名を引数として受け取ります。
そして、受け取った画像ファイルを顔認識に通し、その結果から顔のいい感じの座標に猫耳を乗せます。

## 使用ライブラリ
顔認識のためにfaceplusplusを使用しています。
faceplusplusはmashape越しに使っています。

ちなみにmashapeはいろんなAPIをまとめて簡単に使えるライブラリです。

## 顔認識

顔認識は上記にもあるようにmashape越しにfaceplusplusを使用しています。
いろいろな詳しい結果がとれます。(性別、年齢、笑顔度とかも！)
今回は顔の幅、高さ、中心座標を使っています。
ちなみに座標はピクセルじゃなくて画像の縦横の%で返ってきますのでご注意を。

```
require_once dirname(__FILE__).'/unirest-php/lib/Unirest.php';

  :

  $response = Unirest::get("https://faceplusplus-faceplusplus.p.mashape.com/detection/detect?attribute=glass,pose,gender,age,race,smiling&url=" . $img_url,
    array(
      "X-Mashape-Key" => "K74HWn5JLsmsh6Xrnh6FHDYPI2jzp18pxOpjsnnaIgcHRpvNCc"
    )
  );

  $face_width = $response->body->face[0]->position->width;
  $face_height = $response->body->face[0]->position->height;
  $face_center_x = $response->body->face[0]->position->center->x;
  $face_center_y = $response->body->face[0]->position->center->y;
```

## 画像合成

やるべきことは猫耳の画像を顔のサイズに合わせて拡縮して、顔の中心画像などをもとにのせます。


```
  // 上司の画像の拡張子をもとに画像インスタンスを作る
  $path_splitted = explode(".", $path);
  $ext = $path_splitted[count($path_splitted) - 1];
  switch($ext) {
    case 'png':
      $base_image = imagecreatefrompng($path);
      break;
    case 'gif':
      $base_image = imagecreatefromgif($path);
      break;
    case 'jpg':
      $base_image = imagecreatefromjpeg($path);
      break;
    case 'jpeg':
      $base_image = imagecreatefromjpeg($path);
      break;
    default:
      break;
  }

  // 猫耳画像のインスタンスを作る
  $nekomimi_path = "nekomimi";
  $nekomimi = imagecreatefrompng($nekomimi_path);
  
  // 拡縮していく
  // 猫耳画像のサイズを取得
  list($width_nekomimi, $height_kami) = getimagesize($nekomimi_path);
  // 拡縮後の猫耳画像の横幅を 顔の幅 * 1.6 とする。(1.6という数字は使う猫耳画像のサイズによって変わり得ます。)
  $new_width_nekomimi = $face_width * 1.6;
  // 拡縮後の猫耳画像の高さは拡縮後の横幅と元の幅をもとに算出する
  $new_height_nekomimi = $height_kami * ( $new_width_nekomimi / $width_nekomimi);
  // 拡縮済み猫耳画像ようの空の画像を作る
  $scaled_nekomimi = imagecreatetruecolor($width_base, $height_base);
  // 透過を設定する
  $alpha = imagecolortransparent($nekomimi);
  imagefill($scaled_nekomimi, 0, 0, $alpha);
  imagecolortransparent($scaled_nekomimi, $alpha);
  imagecolortransparent($base_image, $alpha);
  // ここで猫耳画像を拡縮小する
  imagecopyresampled($scaled_nekomimi, $nekomimi, 0, 0, 0, 0, $new_width_nekomimi, $new_height_nekomimi, $width_nekomimi, $height_nekomimi);

  // 猫耳画像を上司画像に貼付ける。($face_center_y * 0.1のところは補正です)
  $result = imagecopy($base_image, $scaled_nekomimi, $face_center_x - ($new_width_nekomimi / 2), $face_center_y - ($new_height_nekomimi / 2) + $face_center_y * 0.1, 0, 0, $width_base, $height_base);
  
  imagepng($base_image, "files2/".$filename);

  // お作法
  imagedestroy($nekomimi);
  imagedestroy($scaled_nekomimi);
  imagedestroy($base_image);

```

## 実際のソース

最終的に下記になりました

```php:api.php
<?php
require_once dirname(__FILE__).'/unirest-php/lib/Unirest.php';

function getSimilarCelebs($filename) {
  $path = "files/".$filename;
  $img_url = "http://orenojs.ddo.jp/files/".$filename;

  $response = Unirest::get("https://faceplusplus-faceplusplus.p.mashape.com/detection/detect?attribute=glass,pose,gender,age,race,smiling&url=" . $img_url,
    array(
      "X-Mashape-Key" => "K74HWn5JLsmsh6Xrnh6FHDYPI2jzp18pxOpjsnnaIgcHRpvNCc"
    )
  );

  $face_width = $response->body->face[0]->position->width;
  $face_height = $response->body->face[0]->position->height;
  $face_center_x = $response->body->face[0]->position->center->x;
  $face_center_y = $response->body->face[0]->position->center->y;

  list($width_base, $height_base) = getimagesize($path);

  $face_width = $width_base * ($face_width / 100);
  $face_height = $height_base * ($face_height / 100);
  $face_center_x = $width_base * ($face_center_x / 100);
  $face_center_y = $height_base * ($face_center_y / 100);

  // 上司の画像の拡張子をもとに画像インスタンスを作る
  $path_splitted = explode(".", $path);
  $ext = $path_splitted[count($path_splitted) - 1];
  switch($ext) {
    case 'png':
      $base_image = imagecreatefrompng($path);
      break;
    case 'gif':
      $base_image = imagecreatefromgif($path);
      break;
    case 'jpg':
      $base_image = imagecreatefromjpeg($path);
      break;
    case 'jpeg':
      $base_image = imagecreatefromjpeg($path);
      break;
    default:
      break;
  }

  // 猫耳画像のインスタンスを作る
  $nekomimi_path = "nekomimi";
  $nekomimi = imagecreatefrompng($nekomimi_path);
  
  // 拡縮していく
  // 猫耳画像のサイズを取得
  list($width_nekomimi, $height_kami) = getimagesize($nekomimi_path);
  // 拡縮後の猫耳画像の横幅を 顔の幅 * 1.6 とする。(1.6という数字は使う猫耳画像のサイズによって変わり得ます。)
  $new_width_nekomimi = $face_width * 1.6;
  // 拡縮後の猫耳画像の高さは拡縮後の横幅と元の幅をもとに算出する
  $new_height_nekomimi = $height_kami * ( $new_width_nekomimi / $width_nekomimi);
  // 拡縮済み猫耳画像ようの空の画像を作る
  $scaled_nekomimi = imagecreatetruecolor($width_base, $height_base);
  // 透過を設定する
  $alpha = imagecolortransparent($nekomimi);
  imagefill($scaled_nekomimi, 0, 0, $alpha);
  imagecolortransparent($scaled_nekomimi, $alpha);
  imagecolortransparent($base_image, $alpha);
  // ここで猫耳画像を拡縮小する
  imagecopyresampled($scaled_nekomimi, $nekomimi, 0, 0, 0, 0, $new_width_nekomimi, $new_height_nekomimi, $width_nekomimi, $height_nekomimi);

  // 猫耳画像を上司画像に貼付ける。($face_center_y * 0.1のところは補正です)
  $result = imagecopy($base_image, $scaled_nekomimi, $face_center_x - ($new_width_nekomimi / 2), $face_center_y - ($new_height_nekomimi / 2) + $face_center_y * 0.1, 0, 0, $width_base, $height_base);
  
  imagepng($base_image, "files2/".$filename);

  // お作法
  imagedestroy($nekomimi);
  imagedestroy($scaled_nekomimi);
  imagedestroy($base_image);

  return $result;
}

?>
```

## 感想
PHP普段使わないというか、ちゃんとPHP使ったのって3年くらい前なので死ぬほど時間かかりましたorz