Semua Tentang Belajar Teknologi Digital Dalam Kehidupan Sehari - Hari

  • IC Timer 555 yang Multifungsi

    IC timer 555 adalah sirkuit terpadu (chip) yang digunakan dalam berbagai pembangkit timer, pulsa dan aplikasi osilator. Komponen ini digunakan secara luas, berkat kemudahan dalam penggunaan, harga rendah dan stabilitas yang baik

  • Ayo Migrasi TV Digital

    Kami bantu anda untuk memahami lebih jelas mengenai migrasi tv digital, apa sebabnya dan bagaimana efek terhadap kehidupan. Jasa teknisi juga tersedia dan siap membantu instalasi - setting perangkat - pengaturan antena dan distribusi televisi digital ke kamar kos / hotel

  • Bermain DOT Matrix - LOVEHURT

    Project Sederhana dengan Dot Matrix dan Attiny2313. Bisa menjadi hadiah buat teman atau pacarmu yang ulang tahun dengan tulisan dan animasi yang dapat dibuat sendiri.

  • JAM DIGITAL 6 DIGIT TANPA MICRO FULL CMOS

    Jika anda pencinta IC TTL datau CMOS maka project jam digital ini akan menunjukkan bahwa tidak ada salahnya balik kembali ke dasar elektronika digital , sebab semuanya BISA dibuat dengan teknologi jadul

  • Node Red - Kontrol Industri 4.0

    Teknologi kontrol sudah melampaui ekspektasi semua orang dan dengan kemajuan dunia elektronika, kini semakin leluasa berkreasi melalui Node Red

Tampilkan postingan dengan label yolo. Tampilkan semua postingan
Tampilkan postingan dengan label yolo. Tampilkan semua postingan

Senin, 15 Juli 2024

[raspi - yolo] Pendeteksi Orang Pada CCTV Menggunakan Raspi-Yolov5

 


Wah ternyata yolov5 sangat cocok digunakan pada raspberry pi 3 (baca disini dulu), jadi semangat nihh berbagi kegembiraan bersama pembaca. Jadi seperti yang dulu saat saya belajar yolo v3, ujungnya adalah deteksi orang pada cctv yang bisa dibaca disini. Langsung aja kita akan buat script untuk mengetestnya melalui cctv yang ada di kota malang yang lebih ringan daripada di jogja, alamat untuk memilih titiknya di: http://cctv.malangkota.go.id/




Dan script gabungan dari beberapa tulisan sebelumnya saya bagikan seperti berikut :


import sys
import time
import json
import torch
import cv2
import os
import contextlib
from pathlib import Path

os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = '/usr/lib/x86_64-linux-gnu/qt5/plugins'


def draw_boxes(frame, results):
    # Get the bounding boxes, labels, and confidence scores
    bboxes = results.xyxyn[0][:, :-1].numpy()
    labels = results.xyxyn[0][:, -1].numpy()
    confidences = results.xyxyn[0][:, -2].numpy()

    # Define the COCO class label for 'person'
    PERSON_LABEL = 0

    # Draw boxes for persons only
    for bbox, label, confidence in zip(bboxes, labels, confidences):
        if label == PERSON_LABEL:
            x1, y1, x2, y2 = bbox[:4]
            x1 = int(x1 * frame.shape[1])
            y1 = int(y1 * frame.shape[0])
            x2 = int(x2 * frame.shape[1])
            y2 = int(y2 * frame.shape[0])
            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
            cv2.putText(frame, f'Orang {confidence:.2f}', (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 255, 0), 2)


def main(stream_source):
    start_time = time.time()
    # Load YOLOv5 model
    model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)

    # Open the video stream
    cap = cv2.VideoCapture(stream_source)
    if not cap.isOpened():
        print(f"Error: Could not open video stream {stream_source}")
        return

   # start_time = time.time()
    ret, frame = cap.read()
    if not ret:
        print("Error: Could not read frame")
        cap.release()
        return

    # Perform inference
    results = model(frame)

    # Extract bounding boxes and labels
    labels = results.xyxyn[0][:, -1].numpy()
    n_persons = sum(1 for label in labels if label == 0)  # label '0' typically corresponds to 'person' in COCO dataset

    # Calculate processing time
    processing_time = time.time() - start_time

    # Output results as JSON
    output = {
        "orang": n_persons,
        "time": round(processing_time, 2)
    }
    print(json.dumps(output))

    # Save the frame with bounding boxes as JPEG
   
    draw_boxes(frame, results)
    output_image_path = "/home/lampuku/yolov5/output.jpg"
    #results.render()  # This function draws bounding boxes on the frame
    cv2.imwrite(output_image_path, frame)

    cap.release()

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("Usage: python single_detect.py <stream_source>")
    else:
        stream_source = sys.argv[1]
        main(stream_source)

Hasilnya seperti berikut :



Waktu processing memang terlihat lama 23 detik, namun ini adalah waktu yg menunjukkan proses awal fusing layer dari yolov5. Namun jika melakukan deteksi selanjutnya cukup cepat ketika saya mencoba loop detect seperti berikut ini :




Wow dibawah 5 detik, cukup cepat deteksinya lhooo...Kalau ada yg berminat bisa menggabungkannya dengan node-red untuk membuat webui seperti gambar paling atas.




Share:

[raspi - yolo] Menguji Kemampuan Raspberry pi 3B Untuk Pengolahan Gambar Yolo V5

 


Setelah memanfaatkan kekuatan cloud computing untuk pengolahan gambar yolo v3, karena raspberry pi zero w resource nya terbatas (baca dulu disini), maka kini saatnya melakukan upgrade ke seri raspberry pi yang lebih tinggi yaitu raspi 3B yang memang support komputasi 64bit. Jadi berdasarkan bantuan chatGPT disarankan untuk mencoba yolo v5 dimana berbasis engine TORCH sehingga pas dijalankan di arm 64 bit. Jadi jangan lupa instal versi raspbbery pi melalui imagernya yaitu OS lite legacy (bullseye) 64 bit tanpa desktop. Jadi jangan sampai salah install OS karena memang sangat terbatas resource raspi 3B yang quad core CPU 64bit 1.2 Ghz dengan ram 1GB saja.

Jika sudah sukses instalasi OS maka bisa lanjut menghubungkan ke wifi dan gunakan putty untuk ssh ke ip raspi kamu dan jalankan urutan perintah berikut :


1. Update raspi kamu

sudo apt-get update
sudo apt-get upgrade

2. Install python, pip dan git

sudo apt-get install python3
sudo apt-get install python3-pip

sudo apt-get install git

3. Install yolo v5 beserta script requirements-nya

git clone https://github.com/ultralytics/yolov5
cd yolov5

pip3 install -r requirements.txt


4. Install pytorch beserta turunannya

sudo apt-get install libopenblas-dev libblas-dev m4 cmake cython python3-yaml

wget https://github.com/nmilosev/pytorch-arm-builds/releases/download/v1.4/pytorch-1.4.0a0+6bfc3e0-cp37-cp37m-linux_armv7l.whl
pip3 install torch-1.4.0a0+6bfc3e0-cp37-cp37m-linux_armv7l.whl


Kemudian jika instalasi selesai maka dapat menjalankan script contoh detect.py dan usahakan ukuran gambarnya tidak besar.

python detect.py --source nolkm.jpg


Hasilnya sebagai berikut, sangat memuaskan :



Hasil diatas mungkin bisa berbeda jika ada dependencies atau library yang gagal instal atau bahkan salah instal. Saya sangat mengandalkan chatGPT setiap ada kesalahan yang saya temukan dan agak lupa apa saja error yg muncul itu. Dan yang paling penting adalah menggunakan CPU untuk pengolahan gambar karena raspberry pi tidak punya GPU sekelas Nvidia untuk menjalankan torch.

Salah satu error yang saya ingat adalah, karena OS saya tanpa desktop maka runtime QT untuk menampilkan gambar akan selalu dianggap error :


qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/home/lampuku/.local/lib/python3.9/site-packages/cv2/qt/plugins" even though it was found. This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.


Jadi hal ini disolusikan oleh chatGPT dengan melakukan instalasi manual "headless" sebagai berikut :


1. Install QT dan Xwindows environment. Ini mungkin tidak di perlukan jika kamu menggunakan desktop pada raspberry pi 3 kamu


sudo apt-get update
sudo apt-get install libgl1-mesa-glx libxcb-xinerama0
2. Jangan lupa menambahkan ini jika ingin menjalankan yolov5 pada script python


export QT_QPA_PLATFORM_PLUGIN_PATH=/usr/lib/x86_64-linux-gnu/qt5/plugins  # Adjust path as necessary

3. Jika diperlukan install open cv dengan headless environment


pip install opencv-python-headless

4. Lakukan pengecekan instalasi dengan script testing dibawah ini :


import torch
from PIL import Image

# Load YOLOv5 model
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)

# Set image path
image_path = 'path/to/your/image.jpg'

# Perform inference
results = model(image_path)

# Display results
results.show()  # Displays the image with bounding boxes

# Optionally, save the results
results.save(save_dir='results/')  # Saves results in the 'results' directory

Dan jika hasilnya muncul seperti dibawah ini berarti instalasi sudah benar

Fusing layers...
YOLOv5s summary: 213 layers, 7225885 parameters, 0 gradients, 16.4 GFLOPs
Adding AutoShape...

Selanjutnya kita akan mendeteksi orang pada kamera cctv pada tulisan berikutnya disini.

Share:

Minggu, 14 Juli 2024

[raspi - yolo] Google Colab & Ngrok - Mengolah Gambar Untuk Raspi Zero W

 


Cloud computing adalah hal yang cukup lumrah kita temui untuk membantu semua pekerjaan komputasi kita secara jarak jauh dan dimanapun. Saya sering menggunakan vps - google cloud - aws untuk membatu banyak pekerjaan saya dan kali ini saya akan gunakan google colab yang memiliki kemampuan menjalankan script python pada cloud. Permasalahannya adalah jika kita ingin mengakses google colab secara http API /Post /Get maka tidak akan ada IP public yang diberikan oleh google. Sehingga kita membutuhkan fasilitas tunneling "Gratis" bernama NGROK

Ngrok adalah alat yang memungkinkan pengembang untuk mengekspos server lokal ke internet dengan cara yang aman. Ini sangat berguna untuk pengembangan dan pengujian aplikasi web, terutama ketika perlu memeriksa bagaimana aplikasi tersebut berinteraksi dengan layanan eksternal atau perangkat lain yang tidak berada di jaringan lokal. 

Silahkan daftar dengan akun google kamu dan jangan lupa dapatkan authtoken tunneling untuk praktek yang aakan saya contohkan dibawah.



Pada google colab, setelah terkoneksi dengan benar, maka dibutuhkan mengunduh file konfigurasi yolo v3 seperti berikut ini 

!wget https://pjreddie.com/media/files/yolov3.weights
!wget https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg
!wget https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names

Setellah itu perlu menginstall library python untuk  pyngrok sedangkan flask sudah tersedia secara default

!pip install pyngrok

Dan response nya seperti berikut

Collecting pyngrok Downloading pyngrok-7.1.6-py3-none-any.whl (22 kB) Requirement already satisfied: PyYAML>=5.1 in /usr/local/lib/python3.10/dist-packages (from pyngrok) (6.0.1) Installing collected packages: pyngrok Successfully installed pyngrok-7.1.6

Brikut ini adalah script python untuk mengolah gambar via flask yang mirip dengan tulisan sebelumnya disini . Jangan lupa mengambil authtoken tunnel di dashbor ngrok


from flask import Flask, request, jsonify
import cv2
import numpy as np
import time
from pyngrok import ngrok
import threading



# Replace 'your_authtoken' with your actual authtoken from ngrok dashboard
ngrok.set_auth_token('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')

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 : # 0 = person
                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.imshow("Image", img)
    cv2.imwrite("output.jpg",img)
    #cv2.waitKey(0)
    #cv2.destroyAllWindows()
    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)

    # Measure start time
    start_time = time.time()

    result = detect_objects(image)

    # Measure end time
    end_time = time.time()

    # Calculate processing time
    processing_time = end_time - start_time
    result['processing_time'] = float(processing_time)  # Ensure it's a float

    return jsonify(result)


# Function to run Flask server
def run_flask():
    app.run(port=5000)

# Start Flask server in a separate thread
flask_thread = threading.Thread(target=run_flask)
flask_thread.start()

# Set up ngrok tunnel
public_url = ngrok.connect(5000)
print("Flask server is running at:", public_url)

Sedangkan script pada raspberry pi zero tetap sama dengan tulisan sebelumnya. Jalankan script pada google colab sampai muncul alamat public dari ngrok tunneling.


 * Serving Flask app '__main__'
 * Debug mode: off
INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
INFO:werkzeug:Press CTRL+C to quit
Flask server is running at: NgrokTunnel: "https://029a-34-105-62-129.ngrok-free.app" -> "http://localhost:5000"


Hasilnya luar biasa cepat dan gratis pula !




Dikarenakan alamat publik dari tunneling ngrok berubah setiap kali script dijalankan pada google colab, maka saya sudah berhasil mengakalinya dengan memanfaatkan MQTT sebagai pengirim alamat tunnel nya dan dapat digunakan oleh banyak pengguna semisal banyak raspberry pi zero w + cam di beberapa titik lampu. Ini akan saya bahas jika ada yang tertarik dengan tulisan saya ini (by request).

SELAMAT BELAJAR !
Share:

[raspi - yolo] Memanfaatkan Komputer Lain Untuk Membantu Raspi Zero W Mengolah Gambar

 


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

Yang kita gunakan sebagai server lokal adalah flask yang merupakan pilihan favorit untuk mengetest sistem server berbasis python.  Flask adalah sebuah mikroframework web untuk Python yang dikembangkan oleh Armin Ronacher sebagai bagian dari proyek Pocoo. Flask sangat populer karena kesederhanaannya dan fleksibilitasnya, sehingga memungkinkan pengembang untuk membuat aplikasi web dengan cepat dan efisien.

Fitur Utama Flask

  • 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.

Contoh Aplikasi Sederhana dengan Flask

Berikut adalah contoh dasar aplikasi Flask:
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)

Dan hasilnya sebagai berikut :



Nah...bisa dan cepat bukan ? Jadi file gambar yang saya tampilkan output.jpg diatas merupakan hasil pengolahan gambar pada pc saya sebagai sever dan kemudian dikembalikan ke raspberry pi zero w sebagai json hasil perhitungan jumlah orang. Jadi cukup 1 server bisa melayani banyak alat pengambil gambar yang sama menggunakan raspberry pi zero w yang harganya lumayan murah.

Bagaimana jika PC nya tidak tersedia dan hanya ada jaringan wifi dilokasi ? Kita kan bahas selanjutnya memanfaatkan komputasi cloud dari google lanjut disini.
Share:

[raspi - yolo] Apakah raspberry pi w zero dapat menjalankan yolo ?

 



Wah gak kerasa sudah lama sekali saya tidak menyentuh raspberry pi zero saya hampir 4 tahun setelahnya baru sempat menyentuhnya lagi. Jadi pembaca yang ingin mengetahui bagaimana mengenal seri raspberry pi paling minim dapat kembali ke : https://www.aisi555.com/2020/07/solder-pi-bermain-dengan-gpio-dan.html dan bisa mengenal dasar-dasar raspberry pi dalam konteks GPIO dan padanannya ketika dimanfaatkan layaknya mikrokontroller. 



Kali ini saya yang sedang berkutat dengan dunia image processing berbasis yolo ingin menge-test apakah dengan processor dual core 1Ghz dan ram 512 Kb dapat menjalankan yolo ? Dari beberapa literatur di internet (dan chatgpt tentunya) kita akan menggunakan opencv dan yolo v3 tiny. Tidak lupa saya memformat ulang raspberry pi zero w saya dengan OS terbaru mengunakan software windows - Raspberry Pi Imager dan saya pilihkan Os  lite-32 tanpa desktop agar menghemat space. Jadi saya mengandalkan putty untuk meng-edit semua raspberry saya.



Raspberry Pi Zero W, dengan kekuatan pemrosesan dan memorinya yang terbatas, paling cocok untuk versi ringan YOLO (You Only Look Once) yang dioptimalkan untuk lingkungan dengan sumber daya rendah. Model YOLO umumnya intensif secara komputasi, jadi untuk Raspberry Pi Zero W, Anda harus fokus pada versi yang lebih ringkas yang dirancang untuk efisiensi. Berikut adalah versi yang lebih mungkin kompatibel:

  • YOLOv3 Tiny: Ini adalah versi sederhana dari YOLOv3 yang dirancang agar lebih cepat dan memerlukan lebih sedikit daya komputasi. Ini adalah pilihan bagus untuk perangkat dengan sumber daya terbatas.
  • YOLOv4 Tiny: Mirip dengan YOLOv3 Tiny, ini adalah versi YOLOv4 yang dioptimalkan dan dirancang untuk berjalan pada perangkat dengan kemampuan komputasi lebih rendah.
  • YOLO-Nano: Ini adalah model ringan lainnya yang bertujuan untuk memberikan keseimbangan yang baik antara kinerja dan penggunaan sumber daya.
  • Tiny YOLOv2: Versi ini juga terkenal dengan efisiensinya dan dapat menjadi pilihan yang cocok untuk Raspberry Pi Zero W.

Instalasi dan Pengaturan:

Berikut panduan umum tentang cara menjalankan salah satu model ini di Raspberry Pi Zero W Anda:

1. Instal dependencies:

Pastikan Anda telah menginstal Python (disarankan Python 3).
Instal perpustakaan yang diperlukan seperti NumPy, OpenCV, dan TensorFlow Lite atau PyTorch bergantung pada model dan kerangka kerja yang Anda pilih.

sudo apt-get update
sudo apt-get install python3-pip
sudo pip3 install numpy opencv-python



2. Unduh weight dan Konfigurasi pre-trained:

Unduh file konfigurasi Tiny YOLO dan file bobot. Misalnya, Anda bisa mendapatkan bobot dan konfigurasi YOLOv3 Tiny dari situs web resmi YOLO atau repositori GitHub.
Konversikan ke TensorFlow Lite (Opsional):


wget https://pjreddie.com/media/files/yolov3-tiny.weights
wget https://github.com/pjreddie/darknet/blob/master/cfg/yolov3-tiny.cfg -O yolov3-tiny.cfg
wget https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names


3.Jika menggunakan TensorFlow Lite, konversikan model ke format TensorFlow Lite, yang lebih dioptimalkan untuk perangkat tersemat.

pip3 install tensorflow
Lanjutkan instalasi converter tensorflow lite, jika ini terasa susah skip saja karena saya tidak menggunakannya

4.Jalankan Modelnya:

Tulis skrip untuk memuat model dan menjalankan inferensi. Berikut ini contoh sederhana menggunakan OpenCV dan model YOLOv3 Tiny:

import cv2
import numpy as np

net = cv2.dnn.readNet("yolov3-tiny.weights", "yolov3-tiny.cfg")
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)

def load_image(img_path):
    image = cv2.imread(img_path)
    blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416), swapRB=True, crop=False)
    net.setInput(blob)
    return image

def get_outputs():
    layer_names = net.getLayerNames()
    output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
    return output_layers

def detect_objects(image):
    detections = net.forward(get_outputs())
    for detection in detections:
        for obj in detection:
            scores = obj[5:]
            class_id = np.argmax(scores)
            confidence = scores[class_id]
            if confidence > 0.5:
                center_x = int(obj[0] * image.shape[1])
                center_y = int(obj[1] * image.shape[0])
                w = int(obj[2] * image.shape[1])
                h = int(obj[3] * image.shape[0])
                x = int(center_x - w / 2)
                y = int(center_y - h / 2)
                cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
    return image

image = load_image("your_image.jpg")
output_image = detect_objects(image)
#cv2.imshow("Output", output_image)
#cv2.waitKey(0)
#cv2.destroyAllWindows()


Hasilnya ?


Gagal bokk...ternyata hasil nya sangat  tergantung pada kecerahan gambar dan sangat lambat jika menggunakan gamabr yang lebih besar resolusinya.


wah saya padahal punya proyek untuk mengatur nyala lampu dengan perbandingan jumlah orang dibawah lampu... lalu bagaimana ? Pada bagian selanjutnya saya akan memanfaatkan "komputer lain " yang akan dipinjam kekuatan komputasinya. Apakah google cloud bisa? Silahkan lanjut baca disini.. 

Share:

Jumat, 12 Januari 2024

[Node Red] Deteksi Object Pada CCTV Menggunakan Yolo

 


Tutorial yang akan saya tuliskan pada blog kali ini merupakan penggabungan dari beberapa tulisan maupun video kuliah saya sebelumnya, sehingga untuk kelancaran tutorial harap menyimak pembahasan sebelumnya yaitu :


  • Yolo dan python untuk deteksi objek :  Videonya dilihat disini
  • Menjalankan python pada node-red : Klik disini

Untuk sumber dari gambar capture dari  CCTV bisa mengambil dari berbagai lokasi cctv publik yang ada di internet, dan yang saya pakai pada praktek kali ini adalah CCTV di wilayah jogja yang berbasis wowza sehingga source streamingnya dapat dilihat (melalui cara tertentu). Alamat untuk masuk ke koleksi CCTV kota jogja (paling menarik seputaran malioboro) dapat dilihat di alamat : https://cctv.jogjakota.go.id/. 




Lokasi diatas adalah monumen nol kilometer di ujung malioboro dengan alamat cctv nya : https://cctvjss.jogjakota.go.id/malioboro/NolKm_Timur.stream/chunklist_w221624478.m3u8 . Jadi jika url streaming diatas mati atau berubah, silahkan cari sendiri ya !


Script - Yolo - Python :

import cv2
import numpy as np
import time
import sys

#penghitung waktu proses
starting_time = time.time()

#cmd windows pake spasi biar bisa dieksekusi pada node-red
if len(sys.argv) != 2:
    print("Cara Pakai: python<spasi>script.py<spasi>alamat/stream_url")
    sys.exit(1)

# ambil cmd pada bagian sumber streaming sesuai usage
stream_url = sys.argv[1]

# Open the video stream
cap = cv2.VideoCapture(stream_url)

# ambil 1 frame terakhir aja
ret, img = cap.read()

# alamat direktori yolo harus lengkap
yolo = cv2.dnn.readNet("G:\\IOT\\node_red\\yolov3.weights", "G:\\IOT\\node_red\\yolov3.cfg")
classes = []

with open("G:\\IOT\\node_red\\coco.names", "r") as file:
    classes = [line.strip() for line in file.readlines()]

#proses yolo
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
#img = cv2.imread(name)
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)

# deteksi 3 object orang (0), mobil(2) dan motor(3)
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.5 and ( class_id == 0 or class_id == 2 or class_id == 3): # 3 objek
            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)
			#simpan koordinat dan nilai keyakinan
            boxes.append([x, y, w, h]) 
            confidences.append(float(confidence))
            class_ids.append(class_id)



#perhitungan indeks dan 3 object
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
org = 0
mob = 0
mot = 0

#kotak dan tulisan deteksi objek
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]
        cv2.rectangle(img, (x, y), (x + w, y + h), colorGreen, 3)
        cv2.putText(img, label, (x, y -5), cv2.FONT_HERSHEY_DUPLEX, 2, (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("}")
## dibawah ini pilih mau simpan gambar atau tampilkan saja, sesuaikan kebutuhan
#cv2.imshow("Image", img)
cv2.imwrite("G:\\IOT\\node_red\\output.jpg",img) #
#cv2.waitKey(0)
#cv2.destroyAllWindows()


Hasil dari script diatas berupa string json yang nantinya berguna pada pengolahan data.




Node-Red Flow 


Untuk bagian ini cukup mengikuti pembahasan sebelumnya, dengan perbedaan inject yg digunakan berupa payload alamat stream dari CCTV.




Untuk menampilkan hasil pada flow, maka dibutuhkan pallete yang bernama : node-red-contrib-image-tools , dan untuk melakukan refresh agar tampilannya berubah setelah eksekusi script yolo selesai adalah dengan menggunakan function trigger.




Dengan konfigurasi diatas maka node image viewer akan menampilkan gambar bernama output.jpg setelah 250ms script yolo berhasil dieksekusi. Jika mau langsung import flow nya bisa copas json dibawah ini.


[
    {
        "id": "5e5b156e7f57b6cc",
        "type": "tab",
        "label": "aisi555 dot com",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "d4809067.5e61a",
        "type": "inject",
        "z": "5e5b156e7f57b6cc",
        "name": "nama stream",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": "20",
        "topic": "",
        "payload": "https://cctvjss.jogjakota.go.id/atcs/ATCS_Lampu_Merah_SugengJeroni1.stream/chunklist_w758098670.m3u8",
        "payloadType": "str",
        "x": 190,
        "y": 40,
        "wires": [
            [
                "7a4e8130.b846f8"
            ]
        ]
    },
    {
        "id": "7a4e8130.b846f8",
        "type": "exec",
        "z": "5e5b156e7f57b6cc",
        "command": "python G:\\IOT\\node_red\\yolo_stream.py ",
        "addpay": "payload",
        "append": "",
        "useSpawn": "false",
        "timer": "",
        "winHide": false,
        "oldrc": false,
        "name": "",
        "x": 520,
        "y": 40,
        "wires": [
            [
                "c95a2a0563597a2b",
                "50dcecd33a88080d"
            ],
            [],
            []
        ]
    },
    {
        "id": "c95a2a0563597a2b",
        "type": "debug",
        "z": "5e5b156e7f57b6cc",
        "name": "debug 6",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 920,
        "y": 20,
        "wires": []
    },
    {
        "id": "50dcecd33a88080d",
        "type": "trigger",
        "z": "5e5b156e7f57b6cc",
        "name": "",
        "op1": "",
        "op2": "G:/IOT/node_red/output.jpg",
        "op1type": "nul",
        "op2type": "str",
        "duration": "250",
        "extend": false,
        "overrideDelay": false,
        "units": "ms",
        "reset": "",
        "bytopic": "all",
        "topic": "topic",
        "outputs": 1,
        "x": 920,
        "y": 80,
        "wires": [
            [
                "d6cf44e31cac223d"
            ]
        ]
    },
    {
        "id": "d6cf44e31cac223d",
        "type": "image viewer",
        "z": "5e5b156e7f57b6cc",
        "name": "",
        "width": "800",
        "data": "payload",
        "dataType": "msg",
        "active": true,
        "x": 190,
        "y": 120,
        "wires": [
            []
        ]
    }
]


Dengan kreativitas pembaca maka flows diatas dapat diatur otomatis eksekusi tiap selesai script yolo di eksekusi, mungkin juga berdasarkan waktu atau sebagainya. Mungkin jika komputer kamu super cepat dengan VGA sekelas gamers maka pengolahan gambarnya bisa di level video  (25fps minimal).


Beberapa faktor yang mempengaruhi keberhasilan deteksi object sebagai berikut :

  • Yolo v3 yang digunakan masih menggunakan weights bawaan dari yolo, sehingga tingkat keberhasilan pendeteksiannya hanya dibilang "cukup" karena object yg bisa dideteksi banyak dan umum.
  • Untuk pendeteksian objek yang spesifik dan lebih teliti bisa melakukan training pada object-object yang di kehendaki saja dan akan dibahas pada kesempatan lainnya
  • Tingkat kualitas kamera sangat menentukan deteksi object 

Share:

[Node Red] Script Python Pada Flow Node Red

 


Python sebagai bahasa pemrograman "serba bisa"  sekarang ini cenderung diakomodir untuk bekerjasama (atau pun terpaksa agar lebih up to date) dengan berbagai platform pemrograman visual jaman sekarang. Al hasil - Node Red - sebagai platform pemrograman otomasi "drag and drop" juga memiliki beberapa fasilitas untuk menjalankan script python, baik secara flow/pallete langsung atau memanfaatkan cara paling mudah menurut saya yaitu melalui node eksekusi shell / cmd / terminal  bernama "EXEC".



Sesuai yang kita sudah pahami, perintah shell bermacam-macam yah mungkin jika anda menggunakan CMD pada windows anda bisa menulisakan perintah "date" atau ping ke IP tertentu, semisal ip nya di masukkan ke manual trigger sebagai payload. Output dari node EXEC ada tiga berupa standard output, standar error dan return /exit code. 

Untuk memahami bagaimana cara menjalankan script python pada node red, saya anggap pemahaman python pembaca sudah level dasar, sehingga mudah memahami script dibawah ini untuk membaca inputan dary SYS.ARGV .



Sys.argv akan membaca inputan sebagai list/array dengan anggota yang dipisahkan oleh spasi. Sehingga script diatas jika dijalankan pada shell akan mendapatkan balasan sesuai input yang diberikan. Mari kita pindahkan script ini menjadi bergabung dengan node-red.



Gambar diatas menunjukkan flow node red dimana saya akan menginjekkan suatu nilai msg.payload ke node EXEC dan kemudian akan meng-eksekusi scipt python sederhana pada gambar sebelumnya. Saya akan melakukan append msg.payload dibagian belakang dari perintah shell pythonnya, dan harus diingat semua dependencies dari direktori shellnya harus ditulis dengan lengkap.



Hasilnya seperti pada gambar, ketika saya inject timestamp maka output akan keluar sesuai yang diharapkan dari script pythonnya. Bagaimana jika nilai yang diinject kosong?



Terlihat yang dioutput pada debug node sesuai yang diharapkan, dimana script python akan menjawab "kamu kirim kosong". Dan jika terjadi error semisal coding python saya salah maka debug juga akan memberikan output kesalahan yg dialami asalkan node debugnya diletakkan pada flow yang benar.



Pada tulisan selanjutnya saya akan mempraktekkan kemampuan node-red untuk bekerjasama dengan script python-yolo untuk pengenalan object.




Share:

Kontak Penulis



12179018.png (60×60)
+628155737755

Mail : ahocool@gmail.com

Site View

Categories

555 (8) 7 segmen (3) adc (4) amplifier (2) analog (19) android (12) antares (11) arduino (26) artikel (11) attiny (3) attiny2313 (19) audio (5) baterai (5) blog (1) bluetooth (1) chatgpt (2) cmos (2) crypto (2) dasar (46) digital (11) dimmer (5) display (3) esp8266 (26) euro2020 (13) gcc (1) iklan (1) infrared (2) Input Output (3) iot (72) jam (7) jualan (12) kereta api (1) keyboard (1) keypad (3) kios pulsa (2) kit (6) komponen (17) komputer (3) komunikasi (1) kontrol (8) lain-lain (8) lcd (2) led (14) led matrix (6) line tracer (1) lm35 (1) lora (11) lorawan (2) MATV (1) memory (1) metal detector (4) microcontroller (70) micropython (6) mikrokontroler (1) mikrokontroller (14) mikrotik (5) modbus (9) mqtt (3) ninmedia (5) ntp (1) paket belajar (19) palang pintu otomatis (1) parabola (88) pcb (2) power (1) praktek (2) project (33) proyek (1) python (8) radio (28) raspberry pi (9) remote (1) revisi (1) rfid (1) robot (1) rpm (2) rs232 (1) script break down (3) sdcard (3) sensor (2) sharing (3) signage (1) sinyal (1) sms (6) software (18) solar (1) solusi (1) tachometer (2) technology (1) teknologi (2) telegram (2) telepon (9) televisi (167) television (28) telkomiot (3) transistor (2) troubleshoot (3) tulisan (93) tutorial (108) tv digital (6) tvri (2) vu meter (2) vumeter (2) wav player (3) wayang (1) wifi (3) yolo (7)

Arsip Blog

Diskusi


kaskus
Forum Hobby Elektronika