北科資工二多媒體技術與應用 第三周作業-辨識硬幣與鈔票種類

筆記說明

此筆記用途在於台北科技大學資訊工程系大二下多媒體技術與應用作業紀錄
並非所有人都適用,部分對我而言稍加容易的內容並不會寫在此內。
這是學習後心得的筆記,可能不太適用會未來的學生

由於我沒有學習過裡面的理論,因此這是資工大二學生透過網路與自身理解的筆記,學習價值並不高、且可能擁有大量錯誤。

題目如下,用圖片

由於題目沒有說 1000元要用甚麼顏色,我就用白色

此題作法

此題與北科資工二多媒體技術與應用 第三周作業-辨識硬幣種類大部分相同。
不一樣的部分是此題判斷硬幣與紙鈔是用面積來判斷,因為題目紙鈔有橫者放、直者放,所以要用面積。

考倒我了,嗚嗚。
我對於圖學的知識過少,還需要增加自己對於多媒體的思考能力R。

由於此題已經有告訴你需要用的步驟與規則如下

  • 二值化 ````cv2.threshold```
    給予一數值 x,圖片中大於 x 的點都變成白色,小於的則變成黑色
  • 膨脹 cv2.dilate
    先給予一個矩陣,如果此矩陣裡有白色的點,那所有點都變為白色,要搭配二值化此用
  • 侵蝕 cv2.erode
    先給予一個矩陣,如果此矩陣裡有白色的點,那所有點都變為黑色,要搭配二值化此用
  • 連通物件 cv2.connectedComponentsWithStatsconnectivity=4 時表示判斷區塊的方式是上下左右,connectivity=4 時是上下左右加上左上、左下、右下、右上。
    幫你找出圖片中的所有白色區塊,會給出四個回傳值。
    • num_labels 有多少區塊
    • labels 透過矩陣表示區塊
    • stats 是一個陣列,依序是 x座標、y座標、長、寬、面積,面積以像素為單位
    • centroids 區塊的中心點
  • 圖片大小不可以超過 1000 像素,透過 cv2.resize 進行
  • 對硬幣與鈔票畫線,透過 ````cv2.rectangle``` 進行

現在我們有了這些資訊,就比較好畫圖了。

將資料統整後,可以得出一個結論

  • 圖片大小不可以超過 1000 像素,所以我們先 cv2.resize
  • 再來進行二值化,因為如果沒有二值化後面所有東西都不能做
    至於要在那個點做 x 化就要不斷嘗試
  • 查看圖片,發現還是有很多白點散布在硬幣與鈔票的旁邊,因此先侵蝕
    至於要在矩陣多大就要不斷嘗試
  • 侵蝕完畢後,發現硬幣與鈔票的邊界有點變形,在做膨脹
    至於要在矩陣多大就要不斷嘗試
  • 再來連通物件,print(stat)
    發現有很多圓形,我們先對全部的區塊畫線,檢查有沒有硬幣與鈔票沒有被畫到,或太偏差,有就在回前幾步重新嘗試
  • 確認沒有後,將每種硬幣與鈔票畫線
    不斷找出每種硬幣與鈔票的寬度是多少,以此為依據畫線。
  • 輸出答案

參考連結

提供我所用到的連結
OpenCV中的绘图函数 by OpenCV-Python 中文教程
Error could not find a writer by OpenCV
opencv: 图像缩放(cv2.resize) by JNingWei
How to use openCV’s connected components with stats in python? by stackoverflow
[Python+OpenCV] 畫矩形 rectangle by ShengYu Talk
Orange Color Code by RapidTables

心得

原本在上課老師給的學習時間中不斷嘗試卻一直失敗,果然再不太熟的情況下想要做出一份專案是不可能的壓XD,要先透過別人的資料進行學習,從中得知能做好事的關鍵,然後我們再進行模仿,成功後再進行改良、創新。

謝謝郭梓琳、林紀緯的程式碼,讓我從中學習到這麼多的知識。

放在網路上供我知道,也讓有困難的朋友也能學習到。

題外話,這題的 500 元紙鈔是比 100 元的紙鈔還大的喔,我有用 PS 檢查過

  • 500 元紙鈔長 29.7、高 55.5,單位 cm,面積為 1768.635
  • 100 元紙鈔長 60.82、高 28.58,單位 cm,面積為 1738.2356

不要在寫程式的過程中誤以為 100 元的紙鈔比較大喔XD。

寫了好多 IF,好髒阿QQQ。

重新調整適合的參數位置,二值化、侵蝕、膨脹也是花了我好多時間QQ,圖像也是個大學問。

還有判斷是哪個硬幣也花我很多時間!一開始我是先用寬度來進行判斷,發現紙鈔有一張跟其他擺法不同,後來改用 stat[4] 來解,結果發現跟一般邏輯不同,100 元比 500 元大,1000 元最小,後來才意識到紙鈔的區塊可不一定裡面都沒有區塊阿,也就是可能 100 元的區塊裡面還有一些雜訊,因此 stat[4] 的面積可能就會因此縮小,就因為這樣,才會導致100 元比 500 元大,1000 元最小的問題。
因此要自己用長寬相乘的面積就可以忽略掉雜訊的問題,因此要自己相乘

例如 100 元的區塊中,裡面有雜訊(黑色區塊)此時區塊的面積就會剪掉他。

總之,這讓我學了很多,算開心八XD。

程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import cv2
import numpy as np

img = cv2.imread("../pic/coin2.jpg") #輸入資料
h, w, ch = img.shape #圖片高、寬、通道

img = cv2.resize(img, (w//5, h//5), interpolation=cv2.INTER_NEAREST) #important
#縮小圖片,記住這邊的 interpolation 選擇很重要,如果不確定建議可以都試試找最棒的

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #灰階化,方便閱讀
ret, gray = cv2.threshold(gray, 45, 255, cv2.THRESH_BINARY) #二值化,45 是慢慢設定的


gray = cv2.erode(gray, np.ones((3,3)), iterations=3) #侵蝕,裡面矩陣與 iterations 細調
gray = cv2.dilate(gray, np.ones((3,3)), iterations=2) #膨脹,裡面矩陣與 iterations 細調

#連通物件,設八通道這樣才嚴謹
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(gray, connectivity=8)
print(stats) #檢查所有區塊

ans = 0 #輸出多少錢

for it in stats:
itX = it[0]+it[2] #寬度
itY = it[1]+it[3] #高度
itArea = it[2]*it[3] #面積,忽略掉區塊內雜訊
print(itArea) #可以第一次執行時先印出面積,比較容易在下面 if 的參數做微調
# cv2.rectangle(img, (it[0], it[1]), (itX, itY), (200, 31, 31), 2)
#一開始可以使用,這樣她會畫出所有的區塊來讓你判斷有沒有區塊沒畫到或連在一起

if(itArea >= 1600 and itArea < 2000): #1 dallars
cv2.rectangle(img, (it[0], it[1]), (itX, itY), (0, 0, 255), 2) #BGR
ans += 1
if(itArea >= 2000 and itArea < 2400): #5 dallars
cv2.rectangle(img, (it[0], it[1]), (itX, itY), (0, 165, 255), 2) #BGR
ans += 5
if(itArea >= 3000 and itArea < 3400): #10 dallars
cv2.rectangle(img, (it[0], it[1]), (itX, itY), (0, 255, 255), 2) #BGR
ans += 10
if(itArea >= 3600 and itArea < 4100): #50 dallars
cv2.rectangle(img, (it[0], it[1]), (itX, itY), (0, 128, 0), 2) #BGR
ans += 50
if(itArea >= 55000 and itArea < 57000): #100 dallars
cv2.rectangle(img, (it[0], it[1]), (itX, itY), (200, 31, 31), 2)
ans += 100
if(itArea >= 53000 and itArea < 55000): #500 dallars
cv2.rectangle(img, (it[0], it[1]), (itX, itY), (128, 0, 128), 2)
ans += 500
if(itArea >= 57000 and itArea < 59000): #1000 dallars
cv2.rectangle(img, (it[0], it[1]), (itX, itY), (255, 255, 255), 2)
ans += 1000

print("圖上共有 ",ans ,"元")
cv2.imshow("gray", gray)
cv2.imshow("img", img)

cv2.imwrite('ans3-3.jpg', img)
cv2.imwrite('gray3-3.jpg', gray)
cv2.waitKey(0)

題目資料

硬幣圖片

灰階、二值化、膨脹、侵蝕後的圖片

答案

  • 版權聲明: 本部落格所有文章除有特別聲明外,均採用 Apache License 2.0 許可協議。轉載請註明出處!
  • © 2020-2024 John Doe
  • Powered by Hexo Theme Ayer
  • PV: UV: