ระบบนับเหรียญไทยด้วย LINE และ Roboflow

Model

https://universe.roboflow.com/kittikun/thai-coins-model/model/4

💡 ภาพรวมการทำงาน

  1. ผู้ใช้ส่งภาพเหรียญให้ LINE Bot
  2. Bot ดึงภาพจาก LINE API → แปลงเป็น Base64
  3. ส่งภาพไปให้ Roboflow วิเคราะห์
  4. Roboflow ส่งข้อมูลการตรวจจับกลับมา (class และ confidence)
  5. Bot สรุปผลและส่งกลับไปให้ผู้ใช้

const LINE_TOKEN = 'xxxxxxx';
const ROBOFLOW_API_URL = 'https://serverless.roboflow.com/thai-coins-model/4';
const ROBOFLOW_API_KEY = '4NvR9g70FGKwuhk6zmiG';


function doPost(e) {
  const data = JSON.parse(e.postData.contents);
  const event = data.events[0];

  if (event.type === 'message') {
    const replyToken = event.replyToken;
    let botReply = 'ไม่สามารถประมวลผลได้ในตอนนี้';

    try {
      if (event.message.type === 'image') {
        const base64Image = getLineImageBase64(event.message.id);
        const roboflowResult = processImageWithRoboflowForm(base64Image);
        botReply = roboflowResult || 'ไม่พบเหรียญที่ตรวจจับได้';
      } else {
        botReply = 'กรุณาส่งภาพเหรียญมาเพื่อตรวจสอบ';
      }
    } catch (err) {
      Logger.log('Roboflow Error: ' + err);
      botReply = 'เกิดข้อผิดพลาดในการติดต่อ Roboflow';
    }

    sendMessage(replyToken, { type: 'text', text: botReply.substring(0, 2000) });
  }
}

function sendMessage(replyToken, message) {
  UrlFetchApp.fetch('https://api.line.me/v2/bot/message/reply', {
    method: 'post',
    contentType: 'application/json',
    headers: { Authorization: 'Bearer ' + LINE_TOKEN },
    payload: JSON.stringify({ replyToken, messages: [message] })
  });
}

function getLineImageBase64(messageId) {
  const url = `https://api-data.line.me/v2/bot/message/${messageId}/content`;
  const response = UrlFetchApp.fetch(url, {
    headers: { Authorization: 'Bearer ' + LINE_TOKEN },
    muteHttpExceptions: true
  });
  if (response.getResponseCode() !== 200) {
    throw new Error('ไม่สามารถดึงข้อมูลรูปภาพได้');
  }
  return Utilities.base64Encode(response.getBlob().getBytes());
}

function processImageWithRoboflowForm(base64Image) {
  const url = `${ROBOFLOW_API_URL}?api_key=${ROBOFLOW_API_KEY}`;

  const response = UrlFetchApp.fetch(url, {
    method: 'post',
    contentType: 'application/x-www-form-urlencoded',
    payload: base64Image,
    muteHttpExceptions: true
  });

  Logger.log(response.getContentText());

  const data = JSON.parse(response.getContentText());
  const predictions = data.predictions || [];

  let coinCount = {
    '1 bahts': 0,
    '10 bahts': 0,
    '2 bahts': 0,
    '5 bahts': 0
  };

  predictions.forEach(prediction => {
    if (prediction.confidence >= 0.60 && coinCount.hasOwnProperty(prediction.class)) {
      coinCount[prediction.class]++;
    }
  });

  const totalAmount =
    coinCount['1 bahts'] * 1 +
    coinCount['10 bahts'] * 10 +
    coinCount['2 bahts'] * 2 +
    coinCount['5 bahts'] * 5;

  const totalCoins =
    coinCount['1 bahts'] +
    coinCount['10 bahts'] +
    coinCount['2 bahts'] +
    coinCount['5 bahts'];

  let resultMessage = 'ผลการนับเหรียญ\n';
  resultMessage += `1 บาท: ${coinCount['1 bahts']} เหรียญ\n`;
  resultMessage += `10 บาท: ${coinCount['10 bahts']} เหรียญ\n`;
  resultMessage += `2 บาท: ${coinCount['2 bahts']} เหรียญ\n`;
  resultMessage += `5 บาท: ${coinCount['5 bahts']} เหรียญ\n`;
  resultMessage += `จำนวนเหรียญทั้งหมด: ${totalCoins} เหรียญ\n`;
  resultMessage += `จำนวนเงินทั้งหมด: ${totalAmount} บาท`;

  return resultMessage;
}

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *