python机器学习+opencv实现果蔬识别

一、目的

对输入图像进行图像特征提取,并感受各种不同的特征对最终图像识别的影响。

二、原理

水果有位置、方向、周长、面积、矩形度、宽长比、球状性、圆形度、不变矩、偏心率等各种特征。对图像进行灰度化再经过二值化等处理可以得到图像中水果的轮廓,利用该轮廓可以求得各种特征,利用一些特征构造模型可以实现对水果种类的检测识别。

        以下介绍python中使用opencv库进行图像处理的一些主要函数:

        读入图像:cv2.imread(filepath,flags),显示图像:cv2.imshow(wname,img)

        颜色空间转换:cv2.cvtColor(img,cv2.COLOR_X2Y)

        二值化:cv2.threshold(src, thresh, maxval, type[, dst])

        轮廓提取:cv2.findContours(contour,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

        绘制轮廓:cv2.drawContours()

        求取面积:cv2.contourArea(),求取周长:cv2.arcLength()

一些特征的计算过程如下:

矩形度:

,AO是该物体的面积,而AMER是其外接矩形的面积

球状性:

,ri为最大内接圆半径,rc为最小外接圆半径

圆形度:e=(4π 面积)/(周长 * 周长);

三、实现过程

1.数据集说明

数据集中包含苹果和香蕉两种水果,分别存放于对应的文件夹中

图1 部分数据集

2.提取特征

读入所有的水果图像,首先对它们做如下处理:转为灰度图像、二值化

处理前后图像如下:

图2 原图

图3 二值化图像

接下来提取二值图像的轮廓信息并进行绘制:

轮廓信息如下(部分):

图4 轮廓信息

处理后图片如下:

图5 边缘轮廓绘制

利用轮廓信息可以求得外接矩形,长宽,面积周长等信息

先利用库函数求得图像的外接矩形以及中心点位置:

结果如下:

图6 外接矩形及中心点

计算图像的各种特征:

结果如下:

图7 特征提取结果

得到上述特征后我选择宽长比、圆形度、矩形度以及矩形度作为训练的特征值。对所有的图片做如上所示相同的操作,将选取的三个特征存放在数组中,结果如下:

图8 训练集特征

设定训练集标签,0代表苹果,1代表香蕉:

图9 训练集标签

通过python sklearn库可以构造svm分类器进行训练:

训练结果如下:

图10 训练结果

可以看出此时训练集准确率已经达到了100%

3.水果预测

选择训练集之外的苹果或者香蕉图像进行预测

载入测试图片与训练集做相同的操作,得到三种特征值,预测函数如下:

预测:

图11 测试1 苹果原图

图12 测试结果1

此时观察到其宽长比似乎异常,查看其二值化及结果图片如下:

图13 异常结果1

可以看出结果错误的,发现是由于其阴影部分及背景部分的影响,训练集由于照片都是黑色背景所以处理方便,而对于额外随意的水果照片需要进行不同的处理才能准确分割出水果。

图14 测试2 苹果原图

修改二值化阈值,使其能够准确分割出水果图像:

图15 正确处理图像

图16 测试结果2

图17 测试3 香蕉原图

图18 正确处理后

图19 测试结果3

四、完整代码

import numpy as np
import cv2
import  matplotlib.pyplot as plt
import os
from sklearn import svm,metrics
file_path = 'img'
fru = [cla for cla in os.listdir(file_path) if '.txt' not in cla]
tz=[]
for cla in fru:
    cla_path = file_path + '/' + cla + '/'  # 某一类别动作的子目录
    images = os.listdir(cla_path)  # iamges 列表存储了该目录下所有图像的名称
    print(images)
    for pic in images:
        pic=cla_path+pic
        img = cv2.imread(pic)
        imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        ret, thresh = cv2.threshold(imgray, 8, 255, cv2.THRESH_BINARY)
        kernel = np.ones((3, 3), dtype=np.uint8)
        closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
        image, contours, hierarchy = cv2.findContours(closing, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
        area = []
        for i in contours:
            area.append(cv2.contourArea(i))
        for i in contours:
            if cv2.contourArea(i) == max(area):
                rect = cv2.minAreaRect(i)
                box = cv2.boxPoints(rect)
                box = np.int0(box)
                #cv2.drawContours(img, [box], 0, (0, 0, 255), 2)  # 画矩形框
                (x, y), radius = cv2.minEnclosingCircle(i)
                center = (int(x), int(y))
                radius = int(radius)
                #cv2.circle(img, center, radius, (0, 255, 0), 2)
                w = min(rect[1][0], rect[1][1])  # 宽度
                h = max(rect[1][0], rect[1][1])  # 长度
                wh=w/h
                s = cv2.contourArea(i)#面积
                l= cv2.arcLength(i, True)#周长
                roundness = (4 * np.pi * s) / (l * l) # 圆形度
                r=s/(w*h)#矩形度
                tz.append([wh,roundness,r])
apple=[0 for i in range(22)]
banana=[1 for i in range(20)]
label=apple+banana
tz=np.array(tz)
print('训练特征值:\n',tz)
print('训练标签(0代表苹果,1代表香蕉):\n',label)
clf=svm.SVC()
clf.fit(tz,label)
pre=clf.predict(tz)
print('预测结果:\n',pre)
print('训练集准确率:',metrics.accuracy_score(pre,label))




#测试
img = cv2.imread('1.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 8, 255, cv2.THRESH_BINARY)
kernel = np.ones((3, 3), dtype=np.uint8)
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
image, contours, hierarchy = cv2.findContours(closing, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
area=[]
test=[]
for i in contours:
    area.append(cv2.contourArea(i))

for i in contours:
    if cv2.contourArea(i)==max(area):
        rect = cv2.minAreaRect(i)
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        cv2.drawContours(img,[box],0,(0,0,255),2) #画矩形框
        print('中心点坐标:',rect[0])
        cv2.circle(img,(int(rect[0][0]),int(rect[0][1])),7,128,-1)#绘制中心点
        M=cv2.moments(i)
        M = cv2.HuMoments(M)  # 计算轮廓的Hu矩
        w = min(rect[1][0],rect[1][1])  # 宽度
        h = max(rect[1][0],rect[1][1]) # 长度
        wh = w / h #宽长比
        s = cv2.contourArea(i)  # 面积
        l = cv2.arcLength(i, True)  # 周长
        roundness = (4 * np.pi * s) / (l * l)  # 圆形度
        r = s / (w * h)  # 矩形度
        print('矩形宽度:',w)
        print('矩形长度:',h)
        print('宽长比:', wh)
        print('水果面积:', s)
        print('水果轮廓周长:', l)
        print('圆形度:', roundness)
        print('矩形度:', r)
        print('不变矩:', M)
        test.append([wh, roundness, r])
        print(test)
        str1 = '(' + str(int(rect[0][0]))+ ',' +str(int(rect[0][1])) +')' #把坐标转化为字符串
        cv2.putText(img,str1,(int(rect[0][0])-80,int(rect[0][1])-30),cv2.FONT_HERSHEY_SIMPLEX,1,(255,255,0),1,cv2.LINE_AA)
'''  绘图,如果想查看图片就取消注释
        cv2.namedWindow("img", 0)
        cv2.resizeWindow("img", 680, 480)
        cv2.imshow("img",img)
        cv2.waitKey()
        cv2.destroyAllWindows()'''
def predict(x):
    a=clf.predict(x)
    if a[0]==0:
        print('预测结果为:apple')
    if a[0]==1:
        print('预测结果为:banana')
predict(test)

五、讨论

在实验的过程中,选择合适的阈值可以成功将训练集中的水果图像切分出来,得到轮廓,利用轮廓可以得到一系列相应的特征,实验中选取其中的宽长比、圆形度和矩形度就已经足以区分出苹果和香蕉,苹果的这三个特征都明显远远大于香蕉。而在使用其余照片进行测试时需要注意在图像二值化时不能一概而论,因为不同的图片中背景、光影等信息可能也会差别很大,如果处理不当可能会导致错误的分割,这将会很大程度上影响结果。

  • 27
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
### 回答1: PythonOpenCV库和MediaPipe工具包是可以一起使用的,以实现手势识别的功能。 首先,需要在Python中安装OpenCV库和MediaPipe工具包。可以使用pip命令来安装它们: ``` pip install opencv-python pip install mediapipe ``` 安装完成后,就可以开始使用了。 首先,导入必要的库: ```python import cv2 import mediapipe as mp ``` 接下来,创建一个MediaPipe的Hand对象和一个OpenCV的VideoCapture对象,用于读取摄像头输入: ```python mp_hands = mp.solutions.hands hands = mp_hands.Hands() cap = cv2.VideoCapture(0) ``` 然后,使用一个循环来读取摄像头输入并进行手势识别: ```python while True: ret, frame = cap.read() if not ret: break frame_RGB = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results = hands.process(frame_RGB) if results.multi_handedness: for hand_landmarks in results.multi_hand_landmarks: # 在这里可以对hand_landmarks进行处理和识别手势的操作 cv2.imshow('Gesture Recognition', frame) if cv2.waitKey(1) == ord('q'): break ``` 在循环中,首先将读取到的帧转换为RGB格式,然后使用Hands对象的process方法对该帧进行手势识别。得到的结果存储在results变量中。 在对每个检测到的手部进行循环处理时,可以使用hand_landmarks来获取该手的关键点坐标。可以根据这些关键点的位置和运动轨迹来实现手势的识别和分析。 最后,通过cv2.imshow方法显示图像,并使用cv2.waitKey方法等待用户操作。当用户按下"q"键时,循环终止,程序退出。 通过以上步骤,就可以使用PythonOpenCV库和MediaPipe工具包实现手势识别的功能了。当然,实际的手势识别算法和操作需要根据具体需求进行进一步的开发和优化。 ### 回答2: Python OpenCV和MediaPipe结合使用可以实现手势识别。首先,我们需要安装必要的库和工具,包括Pythonopencv-python、mediapipe和其他依赖项。 然后,我们可以使用MediaPipe提供的HandTracking模块来检测手部的关键点。它使用机器学习模型来识别手势,并返回手部关键点的坐标。我们可以通过OpenCV的视频捕捉模块读取摄像头的实时图像。 接下来,我们通过应用MediaPipe的HandTracking模块获取手部关键点的坐标,并使用OpenCV将这些坐标绘制到图像上,以便我们可以实时看到手部的位置和动作。 完成这些基本的设置后,我们可以定义特定的手势,例如拇指和食指的指尖接触,作为一个简单的示例。我们可以通过检查特定的关键点之间的距离和角度来识别这种手势。如果关键点之间的距离较小并且角度较小,则我们可以确定手势是拇指和食指的指尖接触。 我们可以使用类似的方法来识别其他手势,比如手掌的张开和闭合,拳头的形成等等。我们可以定义一系列规则和阈值来确定特定手势的识别。 最后,我们可以根据检测到的手势执行特定的操作。例如,当识别到拇指和食指的指尖接触时,我们可以触发相机的快门,实现手势拍照。 总之,PythonOpenCV和MediaPipe结合使用可以实现手势识别。我们可以利用MediaPipe的HandTracking模块检测手部关键点,并使用OpenCV实时绘制手势位置。通过定义特定手势的规则,我们可以识别各种手势并执行相应操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

deleteeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值