flask で画像の明度を変換して、そのままダウンロードする
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 819
前提・実現したいこと
flaskで画像の明るさを変換して、そのままユーザーがダウンロードできるようにしたい
参考URL
Flask サーバに保存せずにファイルをアップロード・ダウンロードする
発生している問題・エラーメッセージ
AttributeError: 'SpooledTemporaryFile' object has no attribute 'point'
下記コードのf.pointが使えないようです。
該当のソースコード
from flask import Flask, request, render_template, send_file
from PIL import Image
from io import BytesIO
from werkzeug.datastructures import FileStorage
from skimage import io
app = Flask(__name__)
@app.route('/', methods=["GET", "POST"])
def index():
title = 'This is Fix Image App!!'
if request.method == 'GET':
return render_template('index.html', title=title)
else:
f = request.files['file']
img_bright = f.point(lambda x:x*1.8)
return send_file(img_bright,
attachment_filename=f.filename,
as_attachment=True)
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>{{title}}</h1>
<img src="/static/images/original_yakiniku.jpg" alt="original">
→
<img src="/static/images/fix_yakiniku.jpg" alt="">
<form action="/", method="POST", enctype=multipart/form-data>
<input type="file", name="file">
<input type="submit">
</form>
</body>
</html>
試したこと
jupyter上で下記のようなコードを書いてフォルダ内の画像全てを明るくするという処理をしたのですが、これをflaskに転用できないかとそのままコードを使っています。
original_photos = os.listdir("photos")
count = 1
for p in original_photos:
img = Image.open("photos/{}".format(p))
img_bright = img.point(lambda x:x*1.8)
ftitle, fext = os.path.splitext(p)
img_bright.save("bright/{}.jpg".format(count))
count = count + 1
そして、参考URLのように画像の処理を何も入れずに実装をしてみたのですが、ダウンロードはできるものの、中身が空となってしまいます。
また、
f = request.files['file']
で受け取ったものはimageファイルそのままなのかなと思ってprintしてみたところ、<FileStorage: '1.jpg' ('image/jpeg')>となっていたので違うのかなと思いました。FileStorageとは何でしょうか。ここから画像を明るくする、pointを使えるようにするにはどうしたら良いでしょうか。
補足情報(FW/ツールのバージョンなど)
python 3.6
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+2
明度変換ではないですが、実現したい挙動に似たコードを作成してみました。
(なるべく元のコードを変えないように意識しました)
ディレクトリ構造は、以下のようになります。
$ tree
.
├── main.py
└── templates
└── index.html
1 directory, 2 files
main.py
from flask import Flask, request, render_template, send_file
from PIL import Image, ImageEnhance
import io
app = Flask(__name__)
@app.route('/', methods=["GET", "POST"])
def index():
title = 'This is Fix Image App!!'
if request.method == 'GET':
return render_template('index.html', title=title)
else:
f = request.files['file']
buf = io.BytesIO()
adjust_contrast(f, buf, 1.7)
buf.seek(0)
return send_file(buf,
attachment_filename=f.filename,
as_attachment=True)
def adjust_contrast(input_image, output_image, factor):
image = Image.open(input_image)
enhancer_object = ImageEnhance.Contrast(image)
out = enhancer_object.enhance(factor)
out.save(output_image, 'JPEG')
if __name__ == '__main__':
app.run(debug=True)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>{{title}}</h1>
<form action="/", method="POST", enctype=multipart/form-data>
<input type="file", name="file">
<input type="submit">
</form>
</body>
</html>
実行
以下のように実行してみてください。
python3 main.py
一応、自分の環境では動きました。
フォームから画像アップロード→変換された画像のダウンロード
となります。
デフォルトでは、
http://localhost:5000
でブラウザからアクセスできると思います
注意点など
質問内容を見る限り、質問者さんは、おそらくアップロードされたファイルをファイルシステムに保存したくなかったと予想します。
それを踏まえ、scikit-imageではファイルオブジェクトを入力として簡単に扱えない感じだったので、使うのをやめました。
画像処理としては、PILでコントラストを変更するという程度にとどめています。
(自分はPILにについては、詳しくありません)
また、画像のフォーマットはJPEG固定となっています
何か、質問者さんの気づきにつながれば幸いです。
参考
adjust_contrastの関数は、以下リンクから引用しました
https://www.blog.pythonlibrary.org/2017/10/24/enhancing-photos-with-python/
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
2018/07/04 23:26
ImageEnhanceも初耳でしたが、画像加工には便利そうですね。
助かりました。また機会がありましたら御助力いただければと思います!