demo代码学习

该代码示例展示了一个基于OpenCV的硬币识别系统,它通过摄像头捕获视频流,调整图像尺寸,然后进行高斯滤波、Canny边缘检测、膨胀操作等预处理步骤来提取硬币轮廓。通过轮廓的面积判断硬币的面值,最终计算总金额。用户可以通过滑动条调整阈值参数以优化检测效果。
摘要由CSDN通过智能技术生成

本代码是用于硬币识别

 可以看到左图中共有三个五元硬币,一个一元硬币,以及三个两元硬币,Rs为22

当右图中新加入一个五元硬币,可以看到Rs变为28

接下来将简述该代码的各个部分。

cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
 

cap = cv2.VideoCapture(0)

VideoCapture()中参数是0,表示打开笔记本的内置摄像头

若想打开指定视频,则cap = cv2.VideoCapture(“视频路径”)

cv2.set(propId, value)

用于设置摄像头
propId:设置的视频参数,类型:整数,
    参数详情可参考(85条消息) cv2.VideoCapture.get、set详解_videocapture set_液压姬的博客-CSDN博客       

value: 设置的参数

返回值:bool值:true:不能确保摄像头已接受属性值//  flase:摄像头未接受属性值

该处使用的
cap.set(3, 640)指把视频流的帧(图片)的宽度调成480,3在视频流的帧的宽度,480为高度数值

cap.set(4, 480)指把视频流的帧(图片)的高度调成480,4在视频流的帧的高度,480为宽度的数值

while True:
    success, img = cap.read()
    cv2.imshow("Image", imgStacked)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

 该段表示读取cap视频,并且利用循环持续遍历视频帧,

cap.read()

该函数有两个返回值,success指读取是否成功,img存储读取到的序列。

cv2.waitKey(1)在有按键按下的时候返回按键的ASCII值,否则返回-1

& 0xFF的按位与操作只取cv2.waitKey(1)返回值最后八位,因为有些系统cv2.waitKey(1)的返回值不止八位,ord(‘q’)表示q的ASCII值

该段用于按下q键后break

def preProcessing(img):
    imgPre = cv2.GaussianBlur(img, (5, 5), 3)
    thresh1 = cv2.getTrackbarPos("Threshold1", "Settings")
    thresh2 = cv2.getTrackbarPos("Threshold2", "Settings")
    imgPre = cv2.Canny(imgPre, thresh1, thresh2)
    kernel = np.ones((3, 3), np.uint8)
    imgPre = cv2.dilate(imgPre, kernel, iterations=1)
    imgPre = cv2.morphologyEx(imgPre, cv2.MORPH_CLOSE, kernel)
 
    return imgPre

该函数对img进行处理,返回值为imgPre,首先对imgPre进行高斯去噪

可参考(85条消息) 机器视觉——图像平滑处理_几乎几乎的博客-CSDN博客 

cv2.GaussianBlur(img, (5, 5), 3)

指对img进行处理,高斯矩阵长宽都为5,标准差取3

cv2.getTrackbarPos("Threshold1", "Settings")

用于读取滑动条,通过滑动滑块,改变 getTrackbarPos的值,并赋值给参数,该处第一个参数为创建的 Trackbar 名称,第二个参数为运行时打开的窗口名称,窗口创建下面再讲,

 cv2.Canny(imgPre, thresh1, thresh2)

 用于边缘检测,第一个参数为输入的图像,后两个参数分别为处理过程中的第一二的参数

 不难看出,当thresh1, thresh2数值较小时,可以捕获更多的边缘信息

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

dilate(imgPre, kernel, iterations=1)
morphologyEx(imgPre, cv2.MORPH_CLOSE, kernel)

 以上函数代表对图像进行腐殖操作,具体使用以及介绍可参见(85条消息) 计算机视觉-腐殖&膨胀操作_几乎几乎的博客-CSDN博客(85条消息) 计算机视觉--开闭运算,梯度运算,黑帽礼帽_几乎几乎的博客-CSDN博客

def empty(a):
    pass
 
cv2.namedWindow("Settings")
cv2.resizeWindow("Settings", 640, 240)
cv2.createTrackbar("Threshold1", "Settings", 219, 255, empty)
cv2.createTrackbar("Threshold2", "Settings", 233, 255, empty)

 创建窗口与滑动条

 如图,创建了一个名为Settings的窗口,并且该窗口拥有两个滑动条,每个滑动条的数值上限为255,默认值分别为219,233,窗口大小为640*240,回调参数为empty即跳过,empty中的参数a为滑动条的当前值。

while True:
    success, img = cap.read()
    imgPre = preProcessing(img)
    imgContours, conFound = cvzone.findContours(img, imgPre, minArea=20)
 
    totalMoney = 0
    imgCount = np.zeros((480, 640, 3), np.uint8)
 
    if conFound:
        for count, contour in enumerate(conFound):
            peri = cv2.arcLength(contour['cnt'], True)
            approx = cv2.approxPolyDP(contour['cnt'], 0.02 * peri, True)
 
            if len(approx) > 5:
                area = contour['area']
                x, y, w, h = contour['bbox']
                imgCrop = img[y:y + h, x:x + w]
                # cv2.imshow(str(count),imgCrop)
                imgColor, mask = myColorFinder.update(imgCrop, hsvVals)
                whitePixelCount = cv2.countNonZero(mask)
                # print(whitePixelCount)
 
                if area < 2050:
                    totalMoney += 5
                elif 2050 < area < 2500:
                    totalMoney += 1
                else:
                    totalMoney += 2
    # print(totalMoney)
    cvzone.putTextRect(imgCount, f'Rs.{totalMoney}', (100, 200),scale=10,offset=30,thickness=7)

    imgStacked = cvzone.stackImages(0.5,([img, imgPre],[imgContours,imgCount]))#把图像拼接到一起
    cvzone.putTextRect(imgStacked, f'Rs.{totalMoney}', (50, 50))
 
    cv2.imshow("Image", imgStacked)

cv2.findContours()

用于轮廓检测,其两个返回值分别代表轮廓本身及每条轮廓所对应的属性

关于函数介绍可参见

(85条消息) cv2.findContours() 轮廓检测_cv2轮廓检测_Easennn的博客-CSDN博客

通过轮廓检测,当该轮廓切割线条大于五即认定目标,而后计算其面积,通过面积判断硬币面值,最后以Rs值作为结果输出。 

myColorFinder = ColorFinder(False)
# Custom Orange Color
hsvVals = {'hmin': 0, 'smin': 0, 'vmin': 145, 'hmax': 63, 'smax': 91, 'vmax': 255}

用于颜色检测,当硬币面值不同,大小相同时可用。

详情可见(88条消息) HSV颜色空间中颜色(红、黄、绿、 青、蓝、紫、 粉红、 砖红、 品红)对应的灰度范围_hsv颜色对照表_胖子工作室的博客-CSDN博客

 最后附上完整代码

# -*- coding: utf-8 -*-
"""
Created on Tue May 23 17:27:19 2023

@author: Victor
"""
import cv2
import cvzone
import numpy as np
from cvzone.ColorModule import ColorFinder
 
cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
 
totalMoney = 0
 
myColorFinder = ColorFinder(False)
# Custom Orange Color
hsvVals = {'hmin': 0, 'smin': 0, 'vmin': 145, 'hmax': 63, 'smax': 91, 'vmax': 255}
 
 
 
def empty():
    pass
 
 
cv2.namedWindow("Settings")
cv2.resizeWindow("Settings", 640, 240)
cv2.createTrackbar("Threshold1", "Settings", 219, 255, empty)
cv2.createTrackbar("Threshold2", "Settings", 233, 255, empty)
 
 
def preProcessing(img):
    imgPre = cv2.GaussianBlur(img, (5, 5), 3)
    thresh1 = cv2.getTrackbarPos("Threshold1", "Settings")
    thresh2 = cv2.getTrackbarPos("Threshold2", "Settings")
    imgPre = cv2.Canny(imgPre, thresh1, thresh2)
    kernel = np.ones((3, 3), np.uint8)
    imgPre = cv2.dilate(imgPre, kernel, iterations=1)
    imgPre = cv2.morphologyEx(imgPre, cv2.MORPH_CLOSE, kernel)
 
    return imgPre
 
 
while True:
    success, img = cap.read()
    imgPre = preProcessing(img)
    imgContours, conFound = cvzone.findContours(img, imgPre, minArea=20)
 
    totalMoney = 0
    imgCount = np.zeros((480, 640, 3), np.uint8)
 
    if conFound:
        for count, contour in enumerate(conFound):
            peri = cv2.arcLength(contour['cnt'], True)
            approx = cv2.approxPolyDP(contour['cnt'], 0.02 * peri, True)
 
            if len(approx) > 5:
                area = contour['area']
                x, y, w, h = contour['bbox']
                imgCrop = img[y:y + h, x:x + w]
                # cv2.imshow(str(count),imgCrop)
                imgColor, mask = myColorFinder.update(imgCrop, hsvVals)
                whitePixelCount = cv2.countNonZero(mask)
                # print(whitePixelCount)
 
                if area < 2050:
                    totalMoney += 5
                elif 2050 < area < 2500:
                    totalMoney += 1
                else:
                    totalMoney += 2
 
    # print(totalMoney)
    cvzone.putTextRect(imgCount, f'Rs.{totalMoney}', (100, 200),scale=10,offset=30,thickness=7)

    imgStacked = cvzone.stackImages(0.5,([img, imgPre],[imgContours,imgCount]))#把图像拼接到一起
    cvzone.putTextRect(imgStacked, f'Rs.{totalMoney}', (50, 50))
 
    cv2.imshow("Image", imgStacked)
    # cv2.imshow("imgColor", imgColor)
    #cv2.waitKey(1)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值