12
9

More than 3 years have passed since last update.

ボタン一つで漫画風の画像にできるサービスを作った

Last updated at Posted at 2021-07-19

こんにちは、Yuiです。

引き続き週イチ発信をしていきます。
今週はボタン一つで漫画風の画像にできるサービスを作ったのでその件について書きます。

過去の週イチ発信は以下

使い方

使い方はとても簡単です。

まずは上記URLにアクセスして、画像を選択します。
私が力尽きてトリミング機能の実装をサボったのでエフェクトを合わせる場合は横長の画像の方がうまくいきます。(大体正方形〜2:1ぐらいのサイズなら違和感ありませんでした。)
これはエフェクトの画像サイズを1280px×840pxにしているのですが、入力画像に合わせて伸びるようにしているため、縦長の画像の場合は文字が縦に細長くなってしまうからです。

image.png

画像を選択したら、エフェクト類を自由に選択できます。
エフェクトは人物の背景に入れるものと、画像の上に重ねるものの両方をそれぞれ選択できます。
デフォルトでは何もエフェクトをつけない状態のものを選択しているので、必要に応じて変更してください。

なお、背景にエフェクトを入れる場合は、できるだけ人物と背景の境界線がはっきりしているものを選ばないとうまく探知できないと思います。これは今回機械学習で人物探知をしているのではなく、輪郭抽出をして背景を入れ替える実装にしているからです。

image.png

エフェクトを選んだら変換ボタンをクリックして数秒待てば変換されます。
今回機械学習を使ってないので、かなり早く変換されると思います。

image.png

ちなみに今回サンプルとして利用させてもらったおじさんは以下から取得させてもらいました。
個人的にお気に入りのフリー素材です。

構成

以下のおなじみの構成です。

フロント...Nuxt.js+tailwind css
バックエンド...Python
API化...AWS
ホスティング...Vercel

これまでリリースした〇〇ツクール系のアプリはほとんど同じ構成で組んでいます。

API化などは【LambdaでOpenCVを利用】AWSとOpenCVを利用してポケモン画像でアスキーアート風に変換するAPIを作ったで詳しく書いたので、記事通りやれば作れると思います。

【これまで開発したツクール系アプリたち】
塗り絵ツクール
絵画ツクール
ポケモンAAツクール

工夫したところ

今回、漫画化の部分は多少閾値を調整した以外は以下のYoutubeそのままなので、興味のある方は動画を参考にしてください。

こちらで工夫したところとしては、エフェクトを追加する部分です。

まず、背景エフェクトをつける部分に関しては、輪郭を抽出して切り抜いてから画像と合成するという処理をとっています。

# 背景エフェクトをつける
def back_filter(src, manga, effect, th):
    # グレースケール変換
    img = cv2.bitwise_not(src)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    effect = cv2.cvtColor(effect, cv2.COLOR_BGR2GRAY)

    # スクリーントーン画像を入力画像と同じ大きさにリサイズ
    effect = cv2.resize(effect,(img_gray.shape[1],img_gray.shape[0]))

    # 2値化
    ret, img_binary = cv2.threshold(img_gray, th, 255,cv2.THRESH_BINARY)

    # 輪郭抽出する。
    contours, _ = cv2.findContours(img_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 面積が最大の輪郭を取得する
    contour = max(contours, key=lambda x: cv2.contourArea(x))

    mask = np.zeros_like(img_binary)
    cv2.drawContours(mask, [contour], -1, color=255, thickness=-1)
    effect = np.where(mask == 0, effect, manga)

    # 三値画像と輪郭画像を合成
    return effect

画像の上にかけるエフェクトに関してはもっとシンプルで、単に合成してるだけです。

# フロントエフェクト
def front_filter(manga, effect):

    effect = cv2.resize(effect,(manga.shape[1], manga.shape[0]))
    #マスク画像作成
    mask = effect[:,:,3]

    # エフェクトをグレースケール化
    effect = cv2.cvtColor(effect, cv2.COLOR_BGR2GRAY)

    # 三値画像と輪郭画像を合成
    manga = np.where(mask == 0, manga, effect)
    return manga

上記の構成のため、背景エフェクトはjpgで、画像の上に重ねるエフェクトはpngの背景透過画像を利用しています。

あとがき

今回はほとんど前に作ったツクール系アプリと同じ構成だったので、だいたい半日ぐらいで作れました。
エフェクト画像に関しては、商業利用OKのフリー素材をかきあつめてcanvaで加工して作りました。
他にこんなエフェクトがほしいなどリクエストあれば受け付けております!

それでは最後までお読みいただきありがとうございました!
もし少しでも参考になった、面白いと思ってもらえたらLGTMお願いいたします!

参考

https://youtu.be/FSwKUNp2U5U
https://assets.clip-studio.com/ja-jp/detail?id=1735354
http://www.manga-sozai.com/data/category/line/page/2
https://dddfont.com/
https://irasutomantul.blogspot.com/2020/06/blog-post_61.html#halaman2
https://mangasozai.com/

12
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
9