導(dǎo)讀本文主要介紹使用Python-OpenCV實(shí)現(xiàn)餐盤水果識(shí)別與計(jì)價(jià)的應(yīng)用。
測(cè)試圖像與說(shuō)明
使用圖像,拍攝環(huán)境有待改善(存在光照不均和拍攝角度的影響):
餐盤/菜品識(shí)別一般方法:
(1)識(shí)別餐盤---傳統(tǒng)方法和機(jī)器學(xué)習(xí)/深度學(xué)習(xí)方法;
(2)識(shí)別菜品---機(jī)器學(xué)習(xí)/深度學(xué)習(xí)方法;
本文使用傳統(tǒng)方法識(shí)別餐盤。
效果演示:
算法思路與實(shí)現(xiàn)步驟
思路:傳統(tǒng)方法識(shí)別餐盤---依據(jù)顏色和形狀來(lái)區(qū)分。
具體步驟:
(1)餐盤顏色共三種:白色、綠色、橙色,形狀共兩種:圓形和方形。區(qū)別顏色使用HSV閾值范圍篩選即可,圓形與方形通過(guò)輪廓面積與輪廓最小外接圓面積的比值來(lái)篩選,圓形rate》=0.9,方形《0.9;
(2)水果共三種:蘋果、香蕉、橙子,通過(guò)顏色可以區(qū)分蘋果和橙子,通過(guò)輪廓最小外接矩形的寬高比可以區(qū)分香蕉和橙子;
(3)計(jì)價(jià):盤子和水果的數(shù)量乘以對(duì)應(yīng)的單價(jià)即可;
(4)設(shè)計(jì)UI,計(jì)價(jià)時(shí)顯示收款碼。
Python-OpenCV實(shí)現(xiàn)算法核心代碼與效果如下:
def Recognize_Dish(self,img): #-------------------香蕉檢測(cè)-----------------# banana_num = 0 hsv_img=cv2.cvtColor(img,cv2.COLOR_BGR2HSV) lower_yellow = np.array([15,30,145])#顏色范圍低閾值 upper_yellow = np.array([35,255,255])#顏色范圍高閾值 mask = cv2.inRange(hsv_img,lower_yellow,upper_yellow)#根據(jù)顏色范圍刪選 mask = cv2.medianBlur(mask, 5)#中值濾波 #cv2.imshow(‘mask_banana’, mask) contours,hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) for cnt in contours: rect = cv2.minAreaRect(cnt) box = cv2.boxPoints(rect) box = np.int0(box) width = max(rect[1][0],rect[1][1]) height = min(rect[1][0],rect[1][1]) center = (int(rect[0][0]),int(rect[0][1])) if width 》 180 and height 》 80 and height 《 130: #print(width,height) img = cv2.drawContours(img,[box],0,(0,0,255),2) cv2.putText(img,‘banana’,center,font,1,(255,0,255), 2) banana_num += 1 item_0 = QTableWidgetItem(“%d”%banana_num) self.tableWidget.setItem(8, 0, item_0)
#-------------------蘋果檢測(cè)-----------------# apple_num = 0 lower_apple = np.array([0,50,50])#顏色范圍低閾值 upper_apple = np.array([30,255,255])#顏色范圍高閾值 mask_apple = cv2.inRange(hsv_img,lower_apple,upper_apple)#根據(jù)顏色范圍刪選 mask_apple = cv2.medianBlur(mask_apple, 9)#中值濾波 #cv2.imshow(‘mask_apple’, mask_apple) #cv2.imwrite(‘mask_apple.jpg’, mask_apple) contours2,hierarchy2 = cv2.findContours(mask_apple, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) for cnt2 in contours2: center,radius = cv2.minEnclosingCircle(cnt2) area = cv2.contourArea(cnt2) #print(radius) rate = area / (math.pi * radius *radius) if radius 》 50 and radius 《 75 and rate 《 0.91: #print(radius) cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(0,255,0),2) cv2.putText(img,‘a(chǎn)pple’,(int(center[0]),int(center[1])),font,1,(255,0,0), 2) apple_num += 1 item_1 = QTableWidgetItem(“%d”%apple_num) self.tableWidget.setItem(6, 0, item_1)
#-------------------橘子檢測(cè)-----------------# orange_num = 0 lower_orange = np.array([0,90,60])#顏色范圍低閾值 upper_orange = np.array([60,255,255])#顏色范圍高閾值 mask_orange = cv2.inRange(hsv_img,lower_orange,upper_orange)#根據(jù)顏色范圍刪選 mask_orange = cv2.medianBlur(mask_orange, 5)#中值濾波 #cv2.imshow(‘mask_orange’, mask_orange) #cv2.imwrite(‘mask_orange.jpg’, mask_orange) contours3,hierarchy3 = cv2.findContours(mask_orange, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) for cnt3 in contours3: center,radius = cv2.minEnclosingCircle(cnt3) area = cv2.contourArea(cnt3) #print(radius) rate = area / (math.pi * radius *radius) if radius 》 50 and radius 《 75 and rate 》 0.85: #print(radius) cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(255,0,255),2) cv2.putText(img,‘orange’,(int(center[0]),int(center[1])),font,1,(255,255,0), 2) orange_num += 1 item_2 = QTableWidgetItem(“%d”%orange_num) self.tableWidget.setItem(7, 0, item_2)
#-------------------白色餐盤檢測(cè)-----------------# white_circle_num = 0 white_rect_num = 0 lower_white = np.array([0,0,150])#顏色范圍低閾值 upper_white= np.array([100,55,255])#顏色范圍高閾值 mask_white = cv2.inRange(hsv_img,lower_white,upper_white)#根據(jù)顏色范圍刪選 mask_white = cv2.medianBlur(mask_white, 5)#中值濾波 #cv2.imshow(‘mask_white’, mask_white) #cv2.imwrite(‘mask_white.jpg’, mask_white) contours4,hierarchy4 = cv2.findContours(mask_white, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) for cnt4 in contours4: area = cv2.contourArea(cnt4) center,radius = cv2.minEnclosingCircle(cnt4) #print(radius) rate = area / (math.pi * radius *radius) if radius 》 100 and radius 《 160: #print(radius) if rate 》= 0.9: cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(255,255,0),2) cv2.putText(img,‘white_circle’,(int(center[0]),int(center[1])),font,1,(0,255,0), 2) white_circle_num += 1 elif rate 》0.6 and rate 《 0.9: rect = cv2.minAreaRect(cnt4) box = cv2.boxPoints(rect) box = np.int0(box) #cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(255,0,255),5) img = cv2.drawContours(img,[box],0,(255,255,0),2) cv2.putText(img,‘white_rect’,(int(center[0]),int(center[1])),font,1,(0,255,0), 2) white_rect_num += 1 item_3 = QTableWidgetItem(“%d”%white_circle_num) self.tableWidget.setItem(0, 0, item_3) item_4 = QTableWidgetItem(“%d”%white_rect_num) self.tableWidget.setItem(1, 0, item_4)
#-------------------綠色餐盤檢測(cè)-----------------# green_circle_num = 0 green_rect_num = 0 lower_green = np.array([30,65,65])#顏色范圍低閾值 upper_green= np.array([80,255,255])#顏色范圍高閾值 mask_green = cv2.inRange(hsv_img,lower_green,upper_green)#根據(jù)顏色范圍刪選 mask_green = cv2.medianBlur(mask_green, 5)#中值濾波 #cv2.imshow(‘mask_green’, mask_green) #cv2.imwrite(‘mask_green.jpg’, mask_green) contours5,hierarchy5 = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) for cnt5 in contours5: area = cv2.contourArea(cnt5) center,radius = cv2.minEnclosingCircle(cnt5) #print(radius) rate = area / (math.pi * radius *radius) if radius 》 100 and radius 《 160: #print(radius) if rate 》= 0.9: cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(0,255,0),2) cv2.putText(img,‘green_circle’,(int(center[0]),int(center[1])),font,1,(0,255,255), 2) green_circle_num += 1 elif rate 》0.6 and rate 《 0.9: rect = cv2.minAreaRect(cnt5) box = cv2.boxPoints(rect) box = np.int0(box) #cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(255,0,255),5) img = cv2.drawContours(img,[box],0,(0,255,0),2) cv2.putText(img,‘green_rect’,(int(center[0]),int(center[1])),font,1,(0,255,255), 2) green_rect_num += 1 item_5 = QTableWidgetItem(“%d”%green_circle_num) self.tableWidget.setItem(4, 0, item_5) item_6 = QTableWidgetItem(“%d”%green_rect_num) self.tableWidget.setItem(5, 0, item_6)
#-------------------橙色餐盤檢測(cè)-----------------# orange_circle_num = 0 orange_rect_num = 0 lower_orange_dish = np.array([0,100,100])#顏色范圍低閾值 upper_orange_dish= np.array([15,255,255])#顏色范圍高閾值 mask_orange_dish = cv2.inRange(hsv_img,lower_orange_dish,upper_orange_dish)#根據(jù)顏色范圍刪選 mask_orange_dish = cv2.medianBlur(mask_orange_dish, 5)#中值濾波 #cv2.imshow(‘mask_green’, mask_green) #cv2.imwrite(‘mask_orange_dish.jpg’, mask_orange_dish) contours6,hierarchy6 = cv2.findContours(mask_orange_dish, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) for cnt6 in contours6: area = cv2.contourArea(cnt6) center,radius = cv2.minEnclosingCircle(cnt6) #print(‘----------------’) #print(radius) rate = area / (math.pi * radius *radius) if radius 》 100 and radius 《 160: #print(rate) if rate 》= 0.8: cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(0,255,0),2) cv2.putText(img,‘orange_circle’,(int(center[0]),int(center[1])),font,1,(255,0,255), 2) orange_circle_num += 1 elif rate 》0.3 and rate 《 0.8: rect = cv2.minAreaRect(cnt6) box = cv2.boxPoints(rect) box = np.int0(box) #cv2.circle(img,(int(center[0]),int(center[1])),int(radius),(255,0,255),5) img = cv2.drawContours(img,[box],0,(0,255,0),2) cv2.putText(img,‘orange_rect’,(int(center[0]),int(center[1])),font,1,(255,0,255), 2) orange_rect_num += 1 item_7 = QTableWidgetItem(“%d”%orange_circle_num) self.tableWidget.setItem(2, 0, item_7) item_8 = QTableWidgetItem(“%d”%orange_rect_num) self.tableWidget.setItem(3, 0, item_8)
for i in range(0,9): self.tableWidget.item(i,0).setTextAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter) self.tableWidget.item(i,1).setTextAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignVCenter) #----------------計(jì)算價(jià)格--------------# self.price = self.price_white_circle * white_circle_num + self.price_white_rect * white_rect_num + self.price_orange_circle * orange_circle_num + self.price_orange_rect * orange_rect_num + self.price_green_circle * green_circle_num + self.price_green_rect * green_rect_num + self.price_apple * apple_num + self.price_orange * orange_num + self.price_banana * banana_num print(self.price) return img
結(jié)尾語(yǔ)
(1) 算法只針對(duì)水果和餐盤數(shù)量和形態(tài)較少的情形,方法供參考;
(2) 實(shí)際應(yīng)用將更復(fù)雜,要求更高,一般開(kāi)源的目標(biāo)檢測(cè)網(wǎng)絡(luò)也很難滿足要求;
(3) 常見(jiàn)菜品識(shí)別的實(shí)際應(yīng)用要求:一個(gè)菜只用一張圖片訓(xùn)練或做模板,訓(xùn)練和識(shí)別時(shí)間盡量短,能夠及時(shí)更新使用。所以真正類似的產(chǎn)品并不好做,如果你有好的方法歡迎留言。
—版權(quán)聲明—
來(lái)源: OpenCV與AI深度學(xué)習(xí)
僅用于學(xué)術(shù)分享,版權(quán)屬于原作者。
若有侵權(quán),請(qǐng)聯(lián)系刪除或修改!
編輯:jq
-
代碼
+關(guān)注
關(guān)注
30文章
4838瀏覽量
69139 -
機(jī)器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8447瀏覽量
133130 -
OpenCV
+關(guān)注
關(guān)注
31文章
635瀏覽量
41596 -
python
+關(guān)注
關(guān)注
56文章
4811瀏覽量
85077 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5518瀏覽量
121613
原文標(biāo)題:應(yīng)用實(shí)例 | 手把手教你用OpenCV實(shí)現(xiàn)餐盤水果識(shí)別計(jì)價(jià)程序(附代碼)
文章出處:【微信號(hào):vision263com,微信公眾號(hào):新機(jī)器視覺(jué)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
使用Python實(shí)現(xiàn)xgboost教程
【實(shí)戰(zhàn)】人工智能0基礎(chǔ)入門:基于Python+OpenCV的車牌識(shí)別項(xiàng)目(課程+平臺(tái)實(shí)踐)
![【實(shí)戰(zhàn)】人工智能0基礎(chǔ)入門:基于<b class='flag-5'>Python+OpenCV</b>的車牌<b class='flag-5'>識(shí)別</b>項(xiàng)目(課程+平臺(tái)實(shí)踐)](https://file1.elecfans.com/web3/M00/02/73/wKgZO2dfk8mAYEA8AABDXof-Ezc658.png)
如何用OpenCV進(jìn)行手勢(shì)識(shí)別--基于米爾全志T527開(kāi)發(fā)板
![如何用<b class='flag-5'>OpenCV</b>進(jìn)行手勢(shì)<b class='flag-5'>識(shí)別</b>--基于米爾全志T527開(kāi)發(fā)板](https://file.elecfans.com/web2/M00/08/64/pYYBAGDwFEGADIPWAAFlJOlmLxg664.jpg)
【AI實(shí)戰(zhàn)項(xiàng)目】基于OpenCV的“顏色識(shí)別項(xiàng)目”完整操作過(guò)程
![【AI實(shí)戰(zhàn)項(xiàng)目】基于<b class='flag-5'>OpenCV</b>的“顏色<b class='flag-5'>識(shí)別</b>項(xiàng)目”完整操作過(guò)程](https://file1.elecfans.com/web3/M00/01/9C/wKgZPGdWrW6ALvshAAAgxUs2CfI310.png)
RK3568 + OpenCV 會(huì)碰撞出什么火花?案例詳解:2-1 基于OpenCV的畫(huà)線實(shí)驗(yàn)
一個(gè)月速成python+OpenCV圖像處理
![一個(gè)月速成<b class='flag-5'>python+OpenCV</b>圖像處理](https://file1.elecfans.com/web3/M00/00/7F/wKgZPGdJlvGANv8EAAAl3WfWse8658.png)
如何用OpenCV的相機(jī)捕捉視頻進(jìn)行人臉檢測(cè)--基于米爾NXP i.MX93開(kāi)發(fā)板
手寫圖像模板匹配算法在OpenCV中的實(shí)現(xiàn)
![手寫圖像模板匹配算法在<b class='flag-5'>OpenCV</b>中的<b class='flag-5'>實(shí)現(xiàn)</b>](https://file1.elecfans.com/web1/M00/F4/B4/wKgZoWcxaGqAPU4YAAAPQhF4fVs669.png)
如何實(shí)現(xiàn)Python復(fù)制文件操作
OpenCV圖像識(shí)別C++代碼
opencv圖像識(shí)別有什么算法
opencv-python和opencv一樣嗎
基于OpenCV的人臉識(shí)別系統(tǒng)設(shè)計(jì)
神經(jīng)網(wǎng)絡(luò)的基本原理及Python編程實(shí)現(xiàn)
基于OpenCV DNN實(shí)現(xiàn)YOLOv8的模型部署與推理演示
![基于<b class='flag-5'>OpenCV</b> DNN<b class='flag-5'>實(shí)現(xiàn)</b>YOLOv8的模型部署與推理演示](https://file1.elecfans.com/web2/M00/C2/4A/wKgZomXhidOAS5bgAAA85lM3BAY512.png)
評(píng)論