GGORG revised this gist . Go to revision
4 files changed, 5 insertions, 5 deletions
index.html
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | <html lang="en"> | |
| 3 | 3 | <head> | |
| 4 | 4 | <meta charset="UTF-8"> | |
| 5 | - | <meta name="viewport" c initial-scale=1.0"> | |
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 6 | 6 | <title>Image Classifier</title> | |
| 7 | 7 | <style> | |
| 8 | 8 | #preview { | |
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | </head> | |
| 15 | 15 | <body> | |
| 16 | 16 | <h1>Wczytaj obraz do klasyfikacji</h1> | |
| 17 | - | <form acti method="POST" enctype="multipart/form-data"> | |
| 17 | + | <form active method="POST" enctype="multipart/form-data"> | |
| 18 | 18 | <input type="file" name="image" id="imageInput" accept="image/*" required> | |
| 19 | 19 | <br> | |
| 20 | 20 | <img id="preview" src="#" alt="Image Preview" style="display: none;"> | |
poziom1.py
| @@ -9,7 +9,7 @@ import timm | |||
| 9 | 9 | # ta wersja jest wyuczona na zbiorze ImageNet-21k | |
| 10 | 10 | nazwa_modelu = "swin_large_patch4_window7_224" | |
| 11 | 11 | klasyfikator = timm.create_model(nazwa_modelu, pretrained=True) | |
| 12 | - | # klasyfikator.eval() | |
| 12 | + | # klasyfikator.eval() | |
| 13 | 13 | ||
| 14 | 14 | # Pobierz zbiór ImageNet (1000 klas) | |
| 15 | 15 | import json | |
poziom2_flask.py
| @@ -18,7 +18,7 @@ os.makedirs(UPLOAD_FOLDER, exist_ok=True) | |||
| 18 | 18 | # ta wersja jest wyuczona na zbiorze ImageNet-21k | |
| 19 | 19 | nazwa_modelu = "swin_large_patch4_window7_224" | |
| 20 | 20 | klasyfikator = timm.create_model(nazwa_modelu, pretrained=True) | |
| 21 | - | #klasyfikator.eval() | |
| 21 | + | #klasyfikator.eval() | |
| 22 | 22 | ||
| 23 | 23 | # Pobierz zbiór ImageNet (1000 klas) | |
| 24 | 24 | imagenet_labels_url = "https://raw.githubusercontent.com/anishathalye/imagenet-simple-labels/master/imagenet-simple-labels.json" | |
result.html
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | <html lang="en"> | |
| 3 | 3 | <head> | |
| 4 | 4 | <meta charset="UTF-8"> | |
| 5 | - | <meta name="viewport" c initial-scale=1.0"> | |
| 5 | + | <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| 6 | 6 | <title>Wyniki klasyfikacji</title> | |
| 7 | 7 | </head> | |
| 8 | 8 | <body> | |
GGORG revised this gist . Go to revision
1 file changed, 1 insertion, 1 deletion
index.html
| @@ -17,7 +17,7 @@ | |||
| 17 | 17 | <form acti method="POST" enctype="multipart/form-data"> | |
| 18 | 18 | <input type="file" name="image" id="imageInput" accept="image/*" required> | |
| 19 | 19 | <br> | |
| 20 | - | <img id="preview" src="#" alt="Image Preview" none;"> | |
| 20 | + | <img id="preview" src="#" alt="Image Preview" style="display: none;"> | |
| 21 | 21 | <br> | |
| 22 | 22 | <button type="submit">Klasyfikuj</button> | |
| 23 | 23 | </form> | |
GGORG revised this gist . Go to revision
1 file changed, 1 insertion, 1 deletion
result.html
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | </head> | |
| 8 | 8 | <body> | |
| 9 | 9 | <h1>Wyniki klasyfikacji</h1> | |
| 10 | - | <img src="{{ image_path }}" alt="Uploaded Image" 500px; max-height: 500px;"> | |
| 10 | + | <img src="{{ image_path }}" alt="Uploaded Image" style="max-width: 500px; max-height: 500px;"> | |
| 11 | 11 | <h2>5 najlepszych trafień:</h2> | |
| 12 | 12 | <ol> | |
| 13 | 13 | {% for label, confidence in predictions %} | |
GGORG revised this gist . Go to revision
3 files changed, 65 insertions, 1 deletion
index.html(file created)
| @@ -0,0 +1,45 @@ | |||
| 1 | + | <!DOCTYPE html> | |
| 2 | + | <html lang="en"> | |
| 3 | + | <head> | |
| 4 | + | <meta charset="UTF-8"> | |
| 5 | + | <meta name="viewport" c initial-scale=1.0"> | |
| 6 | + | <title>Image Classifier</title> | |
| 7 | + | <style> | |
| 8 | + | #preview { | |
| 9 | + | max-width: 500px; | |
| 10 | + | max-height: 500px; | |
| 11 | + | margin-top: 20px; | |
| 12 | + | } | |
| 13 | + | </style> | |
| 14 | + | </head> | |
| 15 | + | <body> | |
| 16 | + | <h1>Wczytaj obraz do klasyfikacji</h1> | |
| 17 | + | <form acti method="POST" enctype="multipart/form-data"> | |
| 18 | + | <input type="file" name="image" id="imageInput" accept="image/*" required> | |
| 19 | + | <br> | |
| 20 | + | <img id="preview" src="#" alt="Image Preview" none;"> | |
| 21 | + | <br> | |
| 22 | + | <button type="submit">Klasyfikuj</button> | |
| 23 | + | </form> | |
| 24 | + | ||
| 25 | + | <script> | |
| 26 | + | const imageInput = document.getElementById('imageInput'); | |
| 27 | + | const preview = document.getElementById('preview'); | |
| 28 | + | ||
| 29 | + | imageInput.addEventListener('change', function(event) { | |
| 30 | + | const file = event.target.files[0]; | |
| 31 | + | if (file) { | |
| 32 | + | const reader = new FileReader(); | |
| 33 | + | reader.onload = function(e) { | |
| 34 | + | preview.src = e.target.result; | |
| 35 | + | preview.style.display = 'block'; | |
| 36 | + | }; | |
| 37 | + | reader.readAsDataURL(file); | |
| 38 | + | } else { | |
| 39 | + | preview.style.display = 'none'; | |
| 40 | + | } | |
| 41 | + | }); | |
| 42 | + | </script> | |
| 43 | + | </body> | |
| 44 | + | </html> | |
| 45 | + | ||
poziom2_flask.py
| @@ -53,7 +53,7 @@ def recognize_image(img_path): | |||
| 53 | 53 | def index(): | |
| 54 | 54 | return render_template("index.html") | |
| 55 | 55 | ||
| 56 | - | @app.route('/classify', methods=['POST']) | |
| 56 | + | @app.route('/', methods=['POST']) | |
| 57 | 57 | def classify_image(): | |
| 58 | 58 | if 'image' not in request.files: | |
| 59 | 59 | return redirect(url_for('index')) | |
result.html(file created)
| @@ -0,0 +1,19 @@ | |||
| 1 | + | <!DOCTYPE html> | |
| 2 | + | <html lang="en"> | |
| 3 | + | <head> | |
| 4 | + | <meta charset="UTF-8"> | |
| 5 | + | <meta name="viewport" c initial-scale=1.0"> | |
| 6 | + | <title>Wyniki klasyfikacji</title> | |
| 7 | + | </head> | |
| 8 | + | <body> | |
| 9 | + | <h1>Wyniki klasyfikacji</h1> | |
| 10 | + | <img src="{{ image_path }}" alt="Uploaded Image" 500px; max-height: 500px;"> | |
| 11 | + | <h2>5 najlepszych trafień:</h2> | |
| 12 | + | <ol> | |
| 13 | + | {% for label, confidence in predictions %} | |
| 14 | + | <li>{{ label }}: {{ confidence | round(2) }}</li> | |
| 15 | + | {% endfor %} | |
| 16 | + | </ol> | |
| 17 | + | <a href="/">Powtórz</a> | |
| 18 | + | </body> | |
| 19 | + | </html> | |
GGORG revised this gist . Go to revision
2 files changed, 128 insertions
poziom1.py(file created)
| @@ -0,0 +1,50 @@ | |||
| 1 | + | # Importowanie bibliotek | |
| 2 | + | # Torch - głębokie sieci neuronowe (ang. Deep Neural Networks) | |
| 3 | + | import torch | |
| 4 | + | from torchvision import transforms | |
| 5 | + | from PIL import Image | |
| 6 | + | import timm | |
| 7 | + | ||
| 8 | + | # Wczytaj model Swin Transformer z biblioteki timm | |
| 9 | + | # ta wersja jest wyuczona na zbiorze ImageNet-21k | |
| 10 | + | nazwa_modelu = "swin_large_patch4_window7_224" | |
| 11 | + | klasyfikator = timm.create_model(nazwa_modelu, pretrained=True) | |
| 12 | + | # klasyfikator.eval() | |
| 13 | + | ||
| 14 | + | # Pobierz zbiór ImageNet (1000 klas) | |
| 15 | + | import json | |
| 16 | + | imagenet_labels_url = "https://raw.githubusercontent.com/anishathalye/imagenet-simple-labels/master/imagenet-simple-labels.json" | |
| 17 | + | import requests | |
| 18 | + | labels = json.loads(requests.get(imagenet_labels_url).text) | |
| 19 | + | ||
| 20 | + | # Potok przetwarzania obrazu na potrzeby klasyfikatora | |
| 21 | + | preprocess = transforms.Compose([ | |
| 22 | + | transforms.Resize((224, 224)), # model Swin Transformer bierze na wejściu obrazy 224x224 | |
| 23 | + | transforms.ToTensor(), | |
| 24 | + | transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), # Normalizacja | |
| 25 | + | ]) | |
| 26 | + | ||
| 27 | + | ||
| 28 | + | def recognize_image(img_path): | |
| 29 | + | """Wczytuje obraz z pliku, przetwarza zgodnie z potokiem preprocess a na koniec klasyfikuje""" | |
| 30 | + | img = Image.open(img_path).convert("RGB") | |
| 31 | + | # Dodatkowy wymiar na wejściu | |
| 32 | + | img_tensor = preprocess(img).unsqueeze(0) | |
| 33 | + | ||
| 34 | + | # Predykcja, czyli przypisanie prawdopodobieństw klas do obrazu wejściowego | |
| 35 | + | with torch.no_grad(): | |
| 36 | + | logits = klasyfikator(img_tensor) | |
| 37 | + | probabilities = torch.nn.functional.softmax(logits, dim=-1) | |
| 38 | + | top5_prob, top5_catid = torch.topk(probabilities, 5) | |
| 39 | + | ||
| 40 | + | # Przeliczenie prawdopodobieństw na etykiety klas | |
| 41 | + | results = [(labels[catid], prob.item()) for catid, prob in zip(top5_catid[0], top5_prob[0])] | |
| 42 | + | return results | |
| 43 | + | ||
| 44 | + | ||
| 45 | + | if __name__ == "__main__": | |
| 46 | + | img_path = "obrazek.jpg" | |
| 47 | + | wyjscie_klasyfikatora = recognize_image(img_path) | |
| 48 | + | for i, (label, confidence) in enumerate(wyjscie_klasyfikatora): | |
| 49 | + | print(f"{i + 1}: {label} ({confidence:.2f})") | |
| 50 | + | ||
poziom2_flask.py(file created)
| @@ -0,0 +1,78 @@ | |||
| 1 | + | from flask import Flask, request, render_template, redirect, url_for | |
| 2 | + | import torch | |
| 3 | + | from torchvision import transforms | |
| 4 | + | from PIL import Image | |
| 5 | + | import timm | |
| 6 | + | import json | |
| 7 | + | import requests | |
| 8 | + | import os | |
| 9 | + | ||
| 10 | + | app = Flask(__name__) | |
| 11 | + | UPLOAD_FOLDER = 'static/uploads' | |
| 12 | + | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER | |
| 13 | + | ||
| 14 | + | # Folder na załadowane obrazki | |
| 15 | + | os.makedirs(UPLOAD_FOLDER, exist_ok=True) | |
| 16 | + | ||
| 17 | + | # Wczytaj model Swin Transformer z biblioteki timm | |
| 18 | + | # ta wersja jest wyuczona na zbiorze ImageNet-21k | |
| 19 | + | nazwa_modelu = "swin_large_patch4_window7_224" | |
| 20 | + | klasyfikator = timm.create_model(nazwa_modelu, pretrained=True) | |
| 21 | + | #klasyfikator.eval() | |
| 22 | + | ||
| 23 | + | # Pobierz zbiór ImageNet (1000 klas) | |
| 24 | + | imagenet_labels_url = "https://raw.githubusercontent.com/anishathalye/imagenet-simple-labels/master/imagenet-simple-labels.json" | |
| 25 | + | labels = json.loads(requests.get(imagenet_labels_url).text) | |
| 26 | + | ||
| 27 | + | # Potok przetwarzania obrazu na potrzeby klasyfikatora | |
| 28 | + | preprocess = transforms.Compose([ | |
| 29 | + | transforms.Resize((224, 224)), | |
| 30 | + | transforms.ToTensor(), | |
| 31 | + | transforms.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)), | |
| 32 | + | ]) | |
| 33 | + | ||
| 34 | + | def recognize_image(img_path): | |
| 35 | + | """ | |
| 36 | + | Wczytuje obraz z pliku, przetwarza zgodnie z potokiem preprocess a na koniec klasyfikuje | |
| 37 | + | """ | |
| 38 | + | img = Image.open(img_path).convert("RGB") | |
| 39 | + | # Dodatkowy wymiar na wejściu | |
| 40 | + | img_tensor = preprocess(img).unsqueeze(0) | |
| 41 | + | ||
| 42 | + | # Predykcja, czyli przypisanie prawdopodobieństw klas do obrazu wejściowego | |
| 43 | + | with torch.no_grad(): | |
| 44 | + | logits = klasyfikator(img_tensor) | |
| 45 | + | probabilities = torch.nn.functional.softmax(logits, dim=-1) | |
| 46 | + | top5_prob, top5_catid = torch.topk(probabilities, 5) | |
| 47 | + | ||
| 48 | + | # Przeliczenie prawdopodobieństw na etykiety klas | |
| 49 | + | results = [(labels[catid], prob.item()) for catid, prob in zip(top5_catid[0], top5_prob[0])] | |
| 50 | + | return results | |
| 51 | + | ||
| 52 | + | @app.route('/') | |
| 53 | + | def index(): | |
| 54 | + | return render_template("index.html") | |
| 55 | + | ||
| 56 | + | @app.route('/classify', methods=['POST']) | |
| 57 | + | def classify_image(): | |
| 58 | + | if 'image' not in request.files: | |
| 59 | + | return redirect(url_for('index')) | |
| 60 | + | ||
| 61 | + | image = request.files['image'] | |
| 62 | + | if image.filename == '': | |
| 63 | + | return redirect(url_for('index')) | |
| 64 | + | ||
| 65 | + | try: | |
| 66 | + | # Zapisz wczytany obraz do katalogu UPLOAD_FOLDER | |
| 67 | + | image_path = os.path.join(app.config['UPLOAD_FOLDER'], image.filename) | |
| 68 | + | image.save(image_path) | |
| 69 | + | ||
| 70 | + | # Klasyfikacja | |
| 71 | + | wyjscie_klasyfikatora = recognize_image(image_path) | |
| 72 | + | return render_template("result.html", image_path=image_path, predictions=wyjscie_klasyfikatora) | |
| 73 | + | except Exception as e: | |
| 74 | + | return str(e), 500 | |
| 75 | + | ||
| 76 | + | if __name__ == "__main__": | |
| 77 | + | app.run(debug=True) | |
| 78 | + | ||