@shosuke240557

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

AIを実装したWebアプリ(犬猫判定)のフロントエンドとバックエンドの接続の仕方(?)がよくわかりません。助けてください。

実現したいこと

  • 犬か猫のjpgを入れるとどちらか判定してくれるwebアプリを作っています。ターミナル上では判定結果が表示されるのですが、ブラウザのフロントエンドではうまくいきません。なんとかしてフロントエンドでもうまく結果が表示される様にしたいです。

前提

スクリーンショット 2023-10-15 16.48.06.png

VSCodeにおいて、Live Serverを使っています。

スクリーンショット 2023-10-15 0.32.05.png

ターミナル上(つまりバックエンドだけ?)ならうまくいきます

スクリーンショット 2023-10-15 16.49.31.png

ブラウザのフロントエンドでやると、コンソールにこの様にエラーが表示されます

スクリーンショット 2023-10-15 0.28.53.png

DogvsCatAPPというファイルの中に関連するものを入れています。h5のやつがトレーニングしたmodelです。DogvsCat.ipynbとdogs-vs-cats(トレーニングに使用した写真が入ってる)は関係ないです(多分)。

発生している問題・エラーメッセージ

Access to fetch at 'http://localhost:5000/predict' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

POST http://localhost:5000/predict net::ERR_FAILED 403 (Forbidden)
classifyImage @ index.html:25
onclick @ index.html:11

Error during fetch operation: TypeError: Failed to fetch
at classifyImage (index.html:25:40)
at HTMLButtonElement.onclick (index.html:11:39)
classifyImage @ index.html:39
await in classifyImage (async)
onclick @ index.html:11

Ensure CORS response header values are valid

該当のソースコード

Python3.8.12(Flask)
from flask import Flask, request, jsonify
import tensorflow as tf
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing import image
import numpy as np
import io
from PIL import Image
from flask_cors import CORS
from flask_cors import cross_origin

app = Flask(__name__)
CORS(app)

# モデルのロード
model = load_model('/Users/shosukesato/DogvsCatAPP/cats_vs_dogs.h5')

@app.route('/predict', methods=['POST'])
@cross_origin()
def predict():
    if 'file' not in request.files:
        return jsonify({'error': 'no file'}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'no filename'}), 400
    
    # 画像の読み込みと前処理
    img = image.load_img(io.BytesIO(file.read()), target_size=(150, 150))
    img_array = image.img_to_array(img)
    img_array_expanded_dims = np.expand_dims(img_array, axis=0)
    preprocessed_img = img_array_expanded_dims / 255.  # モデルのトレーニング時と同じスケーリング
    
    # 予測
    prediction = model.predict(preprocessed_img)
    
    # レスポンスの作成
    if prediction >= 0.5:
        predicted_class = 'dog'
    else:
        predicted_class = 'cat'
    
    response = {'class': predicted_class}
    return jsonify(response), 200, {'Access-Control-Allow-Origin': '*'}

# ローカルでAPIサーバーを実行
if __name__ == '__main__':
    app.run(port=5000, debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Cat or Dog Classifier</title>
</head>
<body>
    <h1>Is it a cat or a dog?</h1>
    <input type="file" id="fileInput" accept="image/*">
    <button onclick="classifyImage()">Classify</button>
    <p id="result"></p>

    <script>
        async function classifyImage() {
            const fileInput = document.getElementById('fileInput');
            const resultParagraph = document.getElementById('result');
            const file = fileInput.files[0];
            const formData = new FormData();
            formData.append('file', file);
    
            resultParagraph.textContent = 'Classifying...';
    
            try {
                const response = await fetch('http://localhost:5000/predict', {
                    method: 'POST',
                    body: formData
                });
    
                if (!response.ok) {
                    console.error('Network response was not ok:', response);
                    resultParagraph.textContent = 'Network response was not ok';
                    return;
                }
    
                const result = await response.json();
                resultParagraph.textContent = `It's a ${result.class}!`;
            } catch (error) {
                console.error('Error during fetch operation:', error);
                resultParagraph.textContent = 'Error during classification';
            }
        }
    </script>    
</body>
</html>

試したこと

ChatGPTに聞いて一日中色々試した結果上記の様なコードになったのですが、もう無理です。

補足情報(FW/ツールのバージョンなど)

macbookairを使っています。初心者で他にどの様な情報が必要かわからないので、何か必要な情報があれば指摘してください。お願いいたします。

0 likes

1Answer

下記記事にCORSの記述がありました。

return jsonify(response), 200, {'Access-Control-Allow-Origin': '*'}

Pythonのソースコード中の'*''http://localhost:5000'に変更してみてはどうでしょうか。

また、別の記事ですが、

フロントエンド側は、先ほどのfetchで投げる際に、mode: "cors"を指定します。

という記述も有りました。

1Like

Comments

  1. @shosuke240557

    Questioner

    ありがとうございました。解決しました!

Your answer might help someone💌