1010 words
5 minutes
AI discord bot image detection for beginner 🤖
2025-06-03

AI discord bot image detection for beginner 🤖#

by ShoIsMyName • Jun 2025

Hallo! (‾◡◝)

วันนี้ผมจะมาสอนสร้าง discord bot ที่สามารถตรวจจับภาพจาก chat แล้วนำมาประมวลผลต่อได้ ซึ่ง mini-project นี้เราจะทำให้ bot ของเรา detect มือ แล้วมาประมวลผลว่ามือเป็น ค้อน กระดาษ หรือกรรไกรรร 🪨📃✂️

Q: แล้วให้มัน detect อย่างอื่นไม่ได้หรอ ? 〒▽〒 A: ได้แน่นอนน แค่เปลี่ยน dataset ที่จะ train model

โดย project ที่นี้เหมาะสำหรับมือใหม่ๆสุดๆ โดยเราจะไม่จำเป็นต้อง setting พวก Layer, Activation function, Hidden layer เลย

🍎 Let start !!#

  1. Gather Dataset 📷

ตอนเด็กเรามักจะได้เห็นสิ่งของ สัตว์หรือภาพตรงหน้า และเรียนรู้ว่าสิ่งๆนั้นมันคืออะไร กระบวนการเรียนรู้แบบนี้คือ เรียนรู้จากข้อมูล , AI ก็เหมือนกัน

สิ่งที่เราต้องมีคือ

  1. Images (ภาพที่ต้องการให้เรียนรู้)
  2. Annotation (สิ่งที่จะบอก AI ว่าวัตถุอยู่ตำแหน่งไหนของภาพ)

ข้อย้อนกลับไปประโยคข้างบนที่ว่า “AI ก็เหมือนกัน” เราจะมาขยายความเล็กๆกันหน่อย เผื่อจะทำให้ทุกคนเห็นภาพในมากขึ้น

ขณะที่ AI หรือ model กำลังเรียนรู้ ข้อมูลที่ส่งเข้าไปข้างในก็จะมีภาพและ annotation, เมื่อมันเห็นข้อมูล มันก็จะปรับ weight ปรับ bias เพื่อทำให้ตัวเลขหรือค่าสถิติเหมาะสมที่พร้อมสำหรับการทำนาย

ความจริง model ไม่ได้เข้าใจภาพจริงๆหรอก มันแค่ใช้ค่าสถิติเพื่อมาวิเคราะห์ภาพเพียงเท่านั้น

Let’s start gathering the images!!#

เราสามารถเอาภาพจาก internet หรือจะถ่ายเอาเองก็ได้ ยิ่งภาพเยอะ ai ก็เรียนรู้ได้เยอะ แต่อย่าลืมนะว่าเราก็ต้องทำ annotation เยอะเช่นกัน (ขั้นตอนนี้เหนื่อยเอาเรื่องเลยล่ะ)

captionless image

ภาพที่เราควรมีควรเป็นภาพที่ความหลากหลาย แต่ยังคงมี object ที่เป็นเป้าหมายของเราอยู่ เช่น จากหัวข้อเราจะทำ AI detect hand เราก็ต้องมีภาพที่มีมืออยู่ในนั้น แนะนำว่าอย่าเป็นมือที่มี background เดิมๆ หาภาพที่มี background ที่แตกต่างกัน, ภาพมือจากองศาต่างๆ ✊🏻🤚🏻✌🏻(ปัญหา overfitting model เดี๋ยวจะอธิบาย) และสุดท้ายคือข้อมูลปลอม

คำถามคือ “ ทำไมต้องใส่ข้อมูลปลอมล่ะ? “

บางคนอาจคิดว่าถ้าเราใส่ข้อมูลปลอมให้ model เรียน มันอาจทำให้ AI ของเราเรียนรู้ข้อมูลที่ผิดและทำให้การ predict แม่นยำน้อยลง..

ความจริงไม่เป็นเช่นนั้น เพราะข้อมูลที่ประกอบกับภาพมันจะมีสิ่งที่เรียกว่า annotation อยู่ด้วย ในทางกลับกัน เมื่อเราใส่ข้อมูลปลอม หรือภาพที่ไม่มีมือ เราก็ไม่ต้องใส่ annotation ลงไป (AI มันจะรู้เองว่าในภาพ มันไม่มีเป้าหมาย)

อีกประเด็นสุดท้าย! ผมขออธิบายเกี่ยวกับ overfitting model

Overfitting model สั้นคือ ความอคติของโมเดลที่เราเทรน ยังไม่เห็นภาพล่ะสิ!..

ขอยก case study อันนึง เรื่องมีอยู่ว่า นาย A ได้การบ้านให้ไปสร้าง AI ที่สามารถตรวจจับคนได้ นาย A เลยหา dataset ที่เป็นภาพตัวเองกำลังยืนในห้อง

captionless image

นาย A ใช้แค่ข้อมูลภาพที่เป็นภาพของตัวเองอย่างเดียว เป็นภาพที่เป็น background เดิม และเสื้อตัวเดิม.. หลัง train ให้ model เสร็จ ผลลัพธ์คือมันสามารถ detect นาย A ได้อย่างแม่นยำ

วันต่อมา.. นาย A เอา AI ที่ภาคภูมิใจไปนำเสนอ.. แต่! แต่!! ทำไมAI ที่ Train มา กลับไม่ Detect อะไรเลย !! ทำไมกันล่ะ?!

นาย A Belike: 😧

นั่นเป็นเพราะว่าสิ่งที่นาย A ได้ train ไปเป็นข้อมูลที่ไม่มีความหลากหลาย และเจาะจงจนเกินไป จน model AI มัน detect เฉพาะคนที่ใส่เสื้อ,กางเกงที่นาย A ใส่เมื่อวาน และ background เป็นห้องที่นาย A ได้ถ่ายเท่านั้น ( เห็นๆเลยว่า AI มันอคติกับข้อมูล )

จบเรื่องของการ gather images แล้ว มาต่อ annotation กันดีกว่า !! 👈(゚ヮ゚👈)

อย่างที่บอกไปว่ามันคือการระบุตำแหน่งของ object ในภาพ

แล้วมันทำยังไงล่ะ ?

ง่ายมากๆ!! ก็แค่ลากกรอบ 4 เหลี่ยมครอบ object

captionless image

ซึ่งการทำ annotation นั้นไม่ได้เป็นเพียงแค่ลากกรอบนะ! แต่เราต้องบันทึกตำแหน่ง x1,y1,x2,y2 ด้วย (ตำแหน่งกรอบของมุมบนซ้ายและล่างขวา) และจดบันทึกข้างหน้าตำแหน่งด้วยว่าอยู่ Class ไหน เช่น Class 0= rock, 1 = paper, 2 = scissors

เช่น 146 225 502 575 0 (146, 225) ตำแหน่ง x,y ที่ระบุตำแหน่งของมุมซ้ายบนของกรอบ (502, 575) เหมือนกัน แต่เป็นขวาล่าง 0 คือ Variable ของ class นั่นก็คือ rock

ซึ่งความจริงลักษณะการ format เก็บข้อมูลสำหรับใช้งาน ก็จะแตกต่างกันไปแล้วแต่ว่าจะใช้กับ library ไหน ถ้าใช้กับ YOLO ก็จะเป็นอีก format นึง

1 0.6703125 0.62421875 0.11015625 0.190625 1 0.4625 0.83046875 0.10625 0.1828125 (Example YOLO format)

ถ้าเราจะทำเองมันก็เหนื่อยเอาเรื่องเลยล่ะ

เลยมี website ที่จะช่วยให้เราลากกรอบและบันทึกข้อมูลและ format ให้อัตโนมัติ ที่ชอบมากๆคือสามารถ Export เป็น format ไหนก็ได้ที่เราต้องการใช้ ที่เราจะใช้คือ YOLOv8 เพราะเราจะใช้มันเทรนด้วย Library YOLO นั่นเองง

เว็บไซต์นั้นคืออออออ….

Roboflow#

[Sign in to Roboflow#

Even if you’re not a machine learning expert, you can use Roboflow train a custom, state-of-the-art computer vision…#

app.roboflow.com](https://app.roboflow.com/?source=post_page-----7a169452d4ed---------------------------------------)

รออะไรกัน เริ่มกันเลย !!

Click project > new project

captionless image

ตั้งชื่อ project name, annotation group ส่วน license ตามใจชอบเลย กด > create public project

upload รูปภาพเราเลย (ผมขอยกตัวอย่างแค่รูปเดียวนะ.. ขี้เกียจ5555)

captionless image

จากนั้นไปแถบ Annotate > Annotate Images > Start Labeling > Assign to myself แล้วกลับไปเมนู Annotate อีกครั้ง

กด Start Annotating ที่มุมบนขวา

captionless image

ให้ลากกรอบแล้วระบุ class ว่าเป็นอะไร

captionless image

ถ้าเสร็จแล้ว กดย้อนกลับเลย และกด Add image to dataset ตรงมุมเดิมเลย (ในเมนู Annotate ที่เดิมที่เรามา)

ไปที่เมนู Versions

ตอนนี้ให้เราทำการตั้งค่าไฟล์ dataset ของเรา

captionless image

อย่าพึ่ง งง นะ! เดี๋ยวเฮียจะอธิบายสั้นๆให้ก่อน ส่วนละเอียดๆ จะอยู่หลังสั้นๆ 😏

Source Images: เลือกรูปที่จะนำเข้า

Train/ Test Split: แบ่งชุดข้อมูล

Preprocessing: แปลงรูปให้เหมาะกับการเข้าโมเดล AI

Augmentation: จำลองสถานการณ์ภาพด้วยการดัดแปลงภาพ

มา !! ได้เวลาอธิบายแบบละเอียด แบบสบายยยๆ~~~~

รู้วิธีการสร้าง dataset กันแล้ว เรามารู้ข้างในกันบ้างดีกว่า ;-)#

ข้อมูลที่จะสอน AI หรือ model นั้นประกอบด้วย train set, valid set, test set

train set มีไว้สอน valid set มีไว้ทดสอบระหว่างสอน test set มีไว้ทดสอบ model เพื่อที่เราจะได้รู้ว่าโมเดลมีความแม่นยำแค่ไหน

แล้วข้อมูลชุดสอนและสอบมันจำเป็นต้องมีการปรับขนาดภาพให้เหมาะสมกับโมเดล เช่น การ resize, grayscale, normalization (ปรับค่าพิกเซลให้อยู่ในช่วง 0–1 เพื่อช่วยให้ AI เรียนรู้ดีขึ้น) อันนี้ก็แล้วแต่เลยในส่วนของ preprocessing

ต่อมา augmentation ก็คือจำลองสถานการณ์ภาพ เช่น ทำให้ภาพเบลอ ภาพแตก เวลาได้ dataset มาก็จะมีภาพที่มีสถานการณ์ต่างๆมาให้ model เรียนรู้ (ภาพนึงใส่ 3 augmentation ก็จะได้เพิ่มอีก 3 ภาพที่มีสถานการณ์ที่เราเลือก)

Create !!#

จากนั้นกด download dataset เลยค้าบเฮีย

เลือก Format YOLOv8

captionless image

สามารถโหลดโดยการ run code หรือ bash ก็ได้ ถ้ากลัว error ก็ Raw URL หรือ กดปุ่ม “Copy Snippet and Open Notebook” เลยย

ถ้ารันใน vscode บางครั้งอาจ error เพราะไม่ได้ติดตั้ง library เราจะหนีปัญหาโดยการใช้ Google colab เลยละกัน55555

จะว่าไปก็ไม่เชิงหนีหรอก เพราะเป็นการแก้ปัญหาสเปคคอมไม่แรงด้วย เพราะการเทรนต้องใช้ cpu หรือ gpu เลย ซึ่ง Google colab ให้เราใช้ gpu ของทางเขาได้ฟรีๆเลย ขอเพียงแค่มีเน็ต :-D

captionless image

ไปที่ website Google colab

[colab.google#

Colab is a hosted Jupyter Notebook service that requires no setup to use and provides free access to computing…#

colab.google](https://colab.google/?source=post_page-----7a169452d4ed---------------------------------------)

กด new notebook แล้วเริ่มกัน

run code ที่ได้มา โค้ดนี้จะเป็นการติดตั้ง dataset ที่เราสร้าง

captionless image

จากนั้นให้เริ่ม train เลย

from ultralytics import YOLO
model = YOLO('yolov8n.pt')
model.train(data='./YOUR_FILE_NAME/data.yaml', epochs=30, imgsz=640)

บอกไว้ก่อนเลยนะว่าต้องมีข้อมูล train, valid , test ไม่งั้น error แหงๆ

epochs คือจำนวนรอบที่จะเทรน ยิ่งเยอะค่า loss ก็ยิ่งต่ำ แต่เวลาเทรนก็สูงเพิ่มขึ้น

imgsz คือขนาดภาพ ในที่นี้คือ 640px

ของผม train ไว้แล้วซึ่งเป็นคนละ dataset ตะกี้คือยกตัวอย่าง

captionless image

captionless image

บอกเลย ตอนเทรนนี่ได้นอนยาววว เพราะมันนาน ขึ้นอยู่กับขนาด dataset และ epochs

เมื่อ train เสร็จก็จะได้ folder พวกนี้มา (ผม train ใน vscode หน้าตาก็จะแตกต่างกันหน่อย)

captionless image

best.pt คือไฟล์ weight ที่พร้อมที่จะใช้งาน

เราสามารถลองเล่นโดยใช้กล้องของเราก็ได้นะ! อ่ะนี่โค้ด!!

import cv2
from ultralytics import YOLO
# ใช้ไฟล์ weight ที่ผ่านการ train เพื่อนำมา predict
model = YOLO('runs/detect/train/weights/best.pt')
# ใช้กล้องโดยระบุตัวที่ 0 ก็คือ webcam ของเรา
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read() # capture frame by frame
if not ret: # ถ้าไม่พบให้ปิด
break
results = model(frame) # เมื่อได้ frame ให้นำไปวิเคราะห์ด้วย model
annotated_frame = results[0].plot() # วาดกรอบลงไปบนภาพ
cv2.imshow("What the hand?", annotated_frame) # ตั้งชื่อจอ
# กด q เพื่อหยุดการทำงาน
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()

หรือจะให้มันอ่านไฟล์ภาพแล้วแสดงผลเอาก็ได้เหมือนกัน

import cv2
from ultralytics import YOLO
model = YOLO('runs/detect/train/weights/best.pt')
image_path = './testingmymodel.jpg'
img = cv2.imread(image_path) # อ่านไฟล์ภาพ
# เก็บ output ไว้ที่ตัวแปร results output บอกว่าเป็น class อะไรและอยู่ตำแหน่งไหน
results = model(img, verbose=False)[0]
print(results.boxes) # print มาดูเฉยๆ555
for box in results.boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0]) # เก็บตำแหน่งมุมบนซ้ายและล่างขวาไว้วาดกรอบ
cls = int(box.cls[0]) # เก็บตัวแปร class
conf = float(box.conf[0]) # ตัวแปร confident (ความมั่นใจของ model)
label = f"{model.names[cls]} ({conf:.2f})" # text ที่จะเขียนบนกรอบ
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) # วาดกรอบ
# ใส่ข้อความบนภาพ
cv2.putText(img, f"Beep! Beep!: {label}", (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.imshow("Detection Result", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# cv2.imwrite("result.jpg", img)

บรรทัดล่างสุดคือเซฟไฟล์ ผม comment ไว้เผื่อคนที่อยากรันแล้วไม่อยากเซฟไฟล์

ถึงขั้นตอนสุดท้ายแล้ววว เมื่อเราทดสอบว่า model ของเราฉลาดมากน้อย อย่างสุดท้ายก็คือการ deploy ไปที่ discord bot 🎉

นี่คือโค้ดที่ใช้กับ discord bot :

import discord
from discord.ext import commands
import aiosqlite
import cv2
from ultralytics import YOLO
import os
import asyncio
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)
# แสดง status ของบอท
@bot.event
async def on_ready():
print(f"{bot.user} is working :-D")
# หน้าที่ของบอท
@bot.event
async def on_message(message):
# ข้าม message ของตัวบอทเอง
if message.author == bot.user:
return
# ถ้าเจอข้อความ
if message.attachments:
for attachment in message.attachments:
# ถ้าข้อความเป็น type image
if attachment.content_type.startswith("image/"):
img_bytes = await attachment.read() # อ่าน bytes ของภาพ
filename = f"received_{attachment.filename}" # สร้างไฟล์ใหม่สำหรับใส่ภาพใหม่
with open(filename, "wb") as f:
f.write(img_bytes) # เอา bytes มาใส่ในไฟล์ภาพที่พึ่งสร้างใหม่ (คล้ายกับการโหลดไฟล์แต่ดีกว่า download ตรงๆ)
await message.channel.send("Processing...")
# Start predict
model = YOLO('weights/best.pt')
img = cv2.imread(filename)
results = model(img, verbose=False)[0]
print(results.boxes)
for box in results.boxes:
x1, y1, x2, y2 = map(int, box.xyxy[0])
cls = int(box.cls[0])
conf = float(box.conf[0])
label = f"{model.names[cls]} ({conf:.2f})"
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.putText(img, f"Beep! Beep!: {label}", (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cv2.imwrite(f"result_{filename}.jpg", img) # SAVE OUTPUT
# ส่งภาพใน chat และลบไฟล์ทั้งหมดออกไปเพื่อ clear memory
await message.channel.send(file=discord.File(f"result_{filename}.jpg"))
os.remove(f"result_{filename}.jpg")
os.remove(filename)
return
await bot.process_commands(message)
# ใส่ token เด้อ เดี๋ยวบอทไม่ทำงาน
bot.run(" CHANGE THIS TO YOUR BOT TOKEN :-D ")

หรือทุกคนสามารถไปดูที่ Github ของผมได้นะ ผมอธิบายวิธีการใช้ไว้แล้ว

[GitHub - ShoIsMyName/Discord-AI-bot-Image-detection: This Discord AI bot will read all the images…#

This Discord AI bot will read all the images in chat and predict whether the hand in the image is a hammer, paper, or…#

github.com](https://github.com/ShoIsMyName/Discord-AI-bot-Image-detection?source=post_page-----7a169452d4ed---------------------------------------)

สุดท้ายนี้ขอบคุณทุกคนที่เข้ามาอ่านนะครับ กู๊ดดบายยเฮียยย!!~~~