重啟撲克機器人之路 -3 :從OCR到程式碼重構的一天

更新 發佈閱讀 8 分鐘

今天繼續在撲克桌況辨識上奮鬥,決定使用OCR來處理文字辨識的部分。相較於OpenHoldem時期需要一個個擷取數字Template進行比對的方式,OCR確實帶來了效率的提升,短短半小時就完成了基礎的辨識功能。

vocus|新世代的創作平台

然而道路總是充滿意想不到的挑戰。在測試不同撲克軟體時,發現介面上的英文字會干擾數字辨識的準確度。原本想說把它們納入辨識區域應該不會有什麼問題,反正在辨識後再取用數字部分即可,結果卻造成了意外的困擾。尋求AI建議後,得到的解決方案反而越來越複雜,就為了處理這麼一個看似簡單的問題。最後我選擇了更務實的做法,直接略過英文字只擷取數字的Region。這個決定讓我再次體會到,在實作中,找到一個「夠用」的解決方案,有時比追求完美的解法更重要。

vocus|新世代的創作平台

下午的時候,開始著手整理Project的程式碼結構。過去總是習慣把所有程式碼都寫在一個Jupyter Notebook裡,結構鬆散且難以維護。今年我決定提早開始規劃程式碼架構,希望能避免之前的慘痛教訓。在AI的指導下,開始把不同功能的程式碼分門別類地放入適當的資料夾中。

poker_detector/
├── src/
│ ├── __init__.py
│ ├── detector/
│ │ ├── __init__.py
│ │ ├── card_detector.py
│ │ ├── text_detector.py
│ │ └── template_matcher.py
│ ├── models/
│ │ ├── __init__.py
│ │ └── card.py
│ ├── utils/
│ │ ├── __init__.py
│ │ ├── image_preprocessing.py
│ │ └── device_connector.py
│ └── config/
│ ├── __init__.py
│ └── regions.py
├── main.py
└── requirements.txt

這個重構過程中遇到了Python模組匯入的老問題 - 從不同資料夾匯入類別或函式總是會出錯。有趣的是,這個問題我之前就遇過好幾次,每次解決後卻總是忘記解法,下次又得重新摸索。這次我決定把解決方案好好記錄下來:必須在每個資料夾建立__init__.py檔案,並在主程式中正確設定路徑。這個看似簡單的問題卻花了我半小時才解決,但至少這次的經驗提醒了我確實記錄的重要性。

import sys
import os

# Get the directory of the current file and append the project root to sys.path

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
#text_detector.py

import cv2

import pytesseract

from src.utils.image_preprocessing import ImagePreprocessor

import numpy as np



class TextDetector:

@staticmethod

def extract_number(text: str) -> float:

numbers = ''.join(c for c in text if c.isdigit() or c == '.')

try:

return float(numbers)

except ValueError:

return 0.0



def detect_text(self, roi: np.ndarray, is_dark_background: bool = False) -> str:

if is_dark_background:

processed = ImagePreprocessor.preprocess_for_ocr_dark_background(roi)

else:

processed = ImagePreprocessor.preprocess_for_ocr(roi)

return pytesseract.image_to_string(processed, config='--psm 7 digits')



def detect_value(self, roi: np.ndarray, is_dark_background: bool = False) -> float:

text = self.detect_text(roi, is_dark_background)

return self.extract_number(text)
#image_preprocessing.py
import cv2

import numpy as np



class ImagePreprocessor:

@staticmethod

def preprocess_for_template(image: np.ndarray) -> np.ndarray:

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

binary = cv2.adaptiveThreshold(

gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,

cv2.THRESH_BINARY_INV, 11, 2

)

kernel = np.ones((3,3), np.uint8)

binary = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)

return binary



@staticmethod

def preprocess_for_ocr(roi: np.ndarray) -> np.ndarray:

gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)

_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

scaled = cv2.resize(binary, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)

denoised = cv2.fastNlMeansDenoising(scaled)

return denoised
留言
avatar-img
傑劉的沙龍
3會員
18內容數
傑劉的沙龍的其他內容
2025/03/16
記錄了對撲克數據庫程式碼的深入理解,以及如何通過精確的查詢獲得準確的分析結果。通過重新組織action type的分類,讓後續的數據分析變得更加高效。這個數據庫將是撲克機器人專案的重要組成部分,用於建立更精確的對手模型。
Thumbnail
2025/03/16
記錄了對撲克數據庫程式碼的深入理解,以及如何通過精確的查詢獲得準確的分析結果。通過重新組織action type的分類,讓後續的數據分析變得更加高效。這個數據庫將是撲克機器人專案的重要組成部分,用於建立更精確的對手模型。
Thumbnail
2025/03/14
記錄了在建構撲克數據庫過程中遇到的挑戰和收穫。探討了自建系統與現成工具的差異,以及如何確保數據準確性。同時反思了精確表達查詢需求的重要性,以及自建系統潛在的長期價值。
Thumbnail
2025/03/14
記錄了在建構撲克數據庫過程中遇到的挑戰和收穫。探討了自建系統與現成工具的差異,以及如何確保數據準確性。同時反思了精確表達查詢需求的重要性,以及自建系統潛在的長期價值。
Thumbnail
2025/03/13
記錄了在撲克機器人開發中從機器學習模型轉向建立自定義數據庫的過程,以及這個策略轉變背後的思考。通過分析真實玩家的行動分布,希望能訓練出更有效的撲克機器人。
Thumbnail
2025/03/13
記錄了在撲克機器人開發中從機器學習模型轉向建立自定義數據庫的過程,以及這個策略轉變背後的思考。通過分析真實玩家的行動分布,希望能訓練出更有效的撲克機器人。
Thumbnail
看更多
你可能也想看
Thumbnail
你一定有玩過猜拳遊戲,但你知道怎麼用Python寫一個猜拳遊戲嗎?今天我要分享一個簡單又好玩的程式碼,讓你可以和電腦對戰! 首先,我們要導入random模組,這個模組可以讓我們隨機生成一個數字,代表電腦出的拳。 然後,我們要用input函數讓使用者輸入自己出的拳,0代表剪刀,1代表石頭,2代表
Thumbnail
你一定有玩過猜拳遊戲,但你知道怎麼用Python寫一個猜拳遊戲嗎?今天我要分享一個簡單又好玩的程式碼,讓你可以和電腦對戰! 首先,我們要導入random模組,這個模組可以讓我們隨機生成一個數字,代表電腦出的拳。 然後,我們要用input函數讓使用者輸入自己出的拳,0代表剪刀,1代表石頭,2代表
Thumbnail
這篇文章將利用之前所學過的一些東西,包括if敘述、串列、while迴圈、函數等等的觀念,來實作一個撲克牌的小遊戲-21點。
Thumbnail
這篇文章將利用之前所學過的一些東西,包括if敘述、串列、while迴圈、函數等等的觀念,來實作一個撲克牌的小遊戲-21點。
Thumbnail
W5 3/18 《曼哈頓》 雖然遊戲規則感覺很簡單,但很重策略(對我來說),要一直思考如何分佈建築才能得高分,還有目標針對誰之類的,但我覺得設計的不錯,很有趣。 《機密代碼》 這款遊戲學校有,我也玩過,但是老師有改一個規則分攤隊長的壓力,我覺得很不錯,是很有效的規則,我們玩了兩局,都是紅隊贏
Thumbnail
W5 3/18 《曼哈頓》 雖然遊戲規則感覺很簡單,但很重策略(對我來說),要一直思考如何分佈建築才能得高分,還有目標針對誰之類的,但我覺得設計的不錯,很有趣。 《機密代碼》 這款遊戲學校有,我也玩過,但是老師有改一個規則分攤隊長的壓力,我覺得很不錯,是很有效的規則,我們玩了兩局,都是紅隊贏
Thumbnail
原版的官方規則導入記分機制,但因為計算過於繁複,所以一般遊玩時較少採用。本變體規則旨在還原原規則的策略性,並保留平常的遊玩樂趣。 1. 配件準備 4枚不同顏色的棋子(紅、藍、黃、綠),以及一張標記0~15的場地。 2. 記分方式 一開始所有棋子都在0的位置。每一局結束時,贏家以外的所有人拿出
Thumbnail
原版的官方規則導入記分機制,但因為計算過於繁複,所以一般遊玩時較少採用。本變體規則旨在還原原規則的策略性,並保留平常的遊玩樂趣。 1. 配件準備 4枚不同顏色的棋子(紅、藍、黃、綠),以及一張標記0~15的場地。 2. 記分方式 一開始所有棋子都在0的位置。每一局結束時,贏家以外的所有人拿出
Thumbnail
演算法就像盲盒,在你滑下一篇前,你永遠不會知道下一篇內容是甚麼。可好處是,這個盲盒是免費的、是廉價的,你可以用大量的時間去「刷」,你可以盡量刷,直到刷到自己喜歡的內容。有時候被低劣的內容吸引也沒關係,畢竟是免費的。可有時會刷到精緻、感興趣的內容,那就太幸運了,把他存起來,然後繼續刷。
Thumbnail
演算法就像盲盒,在你滑下一篇前,你永遠不會知道下一篇內容是甚麼。可好處是,這個盲盒是免費的、是廉價的,你可以用大量的時間去「刷」,你可以盡量刷,直到刷到自己喜歡的內容。有時候被低劣的內容吸引也沒關係,畢竟是免費的。可有時會刷到精緻、感興趣的內容,那就太幸運了,把他存起來,然後繼續刷。
Thumbnail
本篇介紹單人遊戲的核心架構與邏輯,涵蓋發牌、抽牌、出牌及遊戲結算等重要步驟。文章也詳細介紹了使用 socket.io 建立連線的過程,並說明如何利用 React Hooks 管理遊戲狀態,提及後端伺服器如何處理玩家加入房間的事件,並簡要介紹了房間資訊的管理,此文將分為多篇進一步介紹遊戲事件部分。
Thumbnail
本篇介紹單人遊戲的核心架構與邏輯,涵蓋發牌、抽牌、出牌及遊戲結算等重要步驟。文章也詳細介紹了使用 socket.io 建立連線的過程,並說明如何利用 React Hooks 管理遊戲狀態,提及後端伺服器如何處理玩家加入房間的事件,並簡要介紹了房間資訊的管理,此文將分為多篇進一步介紹遊戲事件部分。
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
最近我一直在初心二星徘徊,升不上去。 所以我找了一些資料,用「科學」的方式提升實力。
Thumbnail
最近我一直在初心二星徘徊,升不上去。 所以我找了一些資料,用「科學」的方式提升實力。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
上周來開始把累積沒上的紫微課程拿出來上, 然後上到牌卡, 老師說的一句, 牌卡(其實盤也是)就像是你在學英文, 你光只是看書背單字, 在遇到外國人或是去國外時, 你還是一句話都不會說。 因為英文這個例子太有感, 所以我從星期二, 也是10月17日開始趁GMMTV發佈會那天開始每天試著抽一張牌,
Thumbnail
上周來開始把累積沒上的紫微課程拿出來上, 然後上到牌卡, 老師說的一句, 牌卡(其實盤也是)就像是你在學英文, 你光只是看書背單字, 在遇到外國人或是去國外時, 你還是一句話都不會說。 因為英文這個例子太有感, 所以我從星期二, 也是10月17日開始趁GMMTV發佈會那天開始每天試著抽一張牌,
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
5 月將於臺北表演藝術中心映演的「2026 北藝嚴選」《海妲・蓋柏樂》,由臺灣劇團「晃晃跨幅町」製作,本文將以從舞台符號、聲音與表演調度切入,討論海妲・蓋柏樂在父權社會結構下的困境,並結合榮格心理學與馮.法蘭茲對「阿尼姆斯」與「永恆少年」原型的分析,理解女人何以走向精神性的操控、毀滅與死亡。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News