Judulnya sedikit membuat ambigu, ngapain sih pake raspberry segala kalau juga digunakan PC lain untuk mengolah yolo ? Eiittsss ..saya pingin mensimulasikan raspberry pi zero w saya sebagai pengambil gambar melalui camera raspi ov5647, lalu alat saya ini akan dipasang pada banyak titik untuk medeteksi jumlah orang di bawah lampu jalan. Jadi harga raspi zero w yg cukup murah ditambah camera yg terjangkau menjadi pilihan yang cukup bagus dibanding meng-upgrade ke versi raspi 4 yang jauh harganya walau dapat mengolah gambar dengan lebih bagus (akan di bahas belakangan). Cukup 1 komputer yang processor kelas i5 sudah bisa menjadi server pengolah gambar.
Kali ini saya akan membahas membuat "server" pengolah gambar pada pc saya yang terhubung dengan wifi yang sama dengan raspi zero w yang saya gunakan sebagai simulator pengambil gambar. Untuk itu sebaiknya baca penjelasan sebelumnya untuk memahami yolo-python untuk mendeteksi objek disini:
- Yolo dan python untuk deteksi objek : Videonya dilihat disini
- Deteksi object pada cctv menggunakan python pada node-red : Klik disini
- Ringan dan Fleksibel: Flask tidak memiliki lapisan abstraksi database atau validasi form bawaan, tetapi memungkinkan integrasi dengan banyak pustaka pihak ketiga.
- WSGI: Flask berbasis pada Werkzeug WSGI toolkit dan Jinja2 templating engine.
- Routing: Flask menyediakan sistem routing yang mudah digunakan untuk mengarahkan URL ke fungsi Python.
- Templating: Dengan menggunakan Jinja2, Flask memungkinkan penggunaan template untuk memisahkan logika aplikasi dari tampilan.
- Blueprints: Flask mendukung modularisasi aplikasi melalui blueprints, yang memungkinkan pengembangan aplikasi besar menjadi lebih terstruktur.
- Ekstensi: Banyak ekstensi yang tersedia untuk Flask, seperti Flask-SQLAlchemy untuk ORM, Flask-WTF untuk validasi form, dan Flask-Login untuk otentikasi pengguna.
from flask import Flask, render_template, request, redirect, url_for app = Flask(__name__) @app.route('/') def home(): return 'Hello, Flask!' @app.route('/hello/<name>') def hello(name): return f'Hello, {name}!' @app.route('/form', methods=['GET', 'POST']) def form(): if request.method == 'POST': name = request.form['name'] return redirect(url_for('hello', name=name)) return render_template('form.html') if __name__ == '__main__': app.run(debug=True)
Kalau kita test pada python, hasilnya seperti ini pada browser :
Penjelasan Contoh:
- Importing Flask: Mengimpor Flask dan modul terkait lainnya.
- Inisialisasi Aplikasi: app = Flask(__name__) menginisialisasi aplikasi Flask.
- Route and View Functions: @app.route('/') mendefinisikan route untuk halaman utama. Fungsi home akan mengembalikan string "Hello, Flask!".
- Dynamic Route: @app.route('/hello/<name>') mendefinisikan route dinamis yang menerima parameter name.
- Form Handling: Route /form menerima metode GET dan POST. Jika metode POST, data dari form akan diambil dan pengguna akan diarahkan ke halaman hello.
Kelebihan Flask
- Kesederhanaan: Mudah dipelajari dan digunakan, cocok untuk pemula maupun pengembang berpengalaman.
- Fleksibilitas: Dapat dengan mudah disesuaikan sesuai kebutuhan aplikasi.
- Komunitas: Komunitas yang besar dan aktif, menyediakan banyak tutorial dan dukungan.
Kelemahan Flask
- Kurangnya Fitur Bawaan: Tidak memiliki banyak fitur bawaan seperti framework web lain yang lebih besar (misalnya, Django).
- Pengaturan Manual: Banyak fitur yang harus diatur dan diintegrasikan secara manual.
Flask sangat cocok untuk aplikasi web kecil hingga menengah, API, dan proyek yang membutuhkan fleksibilitas tinggi.
Selanjutnya pada raspi zero w akan saya buat script python untuk mengirimkan gambar ke server saya :
import sys
import requests
import cv2
import time
def send_image(image_path, server_url):
# Read image from file
image = cv2.imread(image_path)
if image is None:
print(f"Failed to load image {image_path}")
return
# Encode image as JPEG
_, img_encoded = cv2.imencode('.jpg', image)
# Measure the start time for the network request
start_time = time.time()
# Send the image to the Flask server
response = requests.post(f"{server_url}/detect", files={"image": img_encoded.tobytes()})
# Measure the end time for the network request
end_time = time.time()
# Calculate network time
network_time = end_time - start_time
# Check and parse the response
response_data = response.json()
server_processing_time_str = response_data.get('processing_time', None)
if server_processing_time_str is not None:
try:
server_processing_time = float(server_processing_time_str)
print(f"Server processing time: {server_processing_time:.2f} seconds")
except ValueError:
print("Error: Server processing time is not a valid float.")
server_processing_time = None
else:
print("Server processing time not found in response.")
server_processing_time = None
print(response_data)
print(f"Network time: {network_time:.2f} seconds")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python myscript.py <image_path> <server_url>")
else:
image_path = sys.argv[1]
server_url = sys.argv[2]
send_image(image_path, server_url)
Script diatas akan menggunakan cara panggil :
python flask.py <nama_gambar.jpg> <ip_server_flask:port>
Sedangkan pada sisi server, seperti yang sudah saya bahas pada cara pengolahan yolo sebelumnya disini, maka script yang saya buat sebagai berikut :
from flask import Flask, request, jsonify
import cv2
import numpy as np
import time
app = Flask(__name__)
yolo = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
classes = []
with open("coco.names", "r") as file:
classes = [line.strip() for line in file.readlines()]
layer_names = yolo.getLayerNames()
output_layers = [layer_names[i - 1] for i in yolo.getUnconnectedOutLayers()]
colorRed = (0,0,255)
colorGreen = (0,255,0)
# #Loading Images
def detect_objects(img):
starting_time = time.time()
height, width, channels = img.shape
# # Detecting objects
blob = cv2.dnn.blobFromImage(img, 0.00392, (255, 255), (0, 0, 0), True, crop=False)
yolo.setInput(blob)
outputs = yolo.forward(output_layers)
class_ids = []
confidences = []
boxes = []
for output in outputs:
for detection in output:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.4 and ( class_id == 0 or class_id == 2 or class_id == 3 ): # 0 = orang, 2 = motor , 3 = mobil
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
org = 0
mob = 0
mot = 0
for i in range(len(boxes)):
if i in indexes:
if class_ids[i] == 0:
org = org + 1
label = 'orang : ' + repr(org)
elif class_ids[i] == 2:
mob = mob + 1
label = 'mobil : ' + repr(mob)
elif class_ids[i] == 3:
mot = mot + 1
label = 'motor : ' + repr(mot)
x, y, w, h = boxes[i]
#label = str(classes[class_ids[i]]) + ', x=' +repr(x) + ',y=' +repr(y)
#label = str(classes[class_ids[i]]) + '- no: ' + repr(i+1)
cv2.rectangle(img, (x, y), (x + w, y + h), colorGreen, 3)
cv2.putText(img, label, (x, y -5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255) )
print("{")
print(f"\"Jumlah Orang\": {org},")
print(f"\"Jumlah Mobil\": {mob},")
print(f"\"Jumlah Motor\": {mot},")
elapsed_time = time.time() - starting_time
print("\"processing time\":" + repr(elapsed_time) )
print("}")
cv2.imwrite("output.jpg",img)
return {"Orang": org, "Mobil": mob, "Motor": mot, "time": elapsed_time }
@app.route("/detect", methods=["POST"])
def detect():
file = request.files["image"]
npimg = np.fromfile(file, np.uint8)
image = cv2.imdecode(npimg, cv2.IMREAD_COLOR)
result = detect_objects(image)
return jsonify(result)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)