打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
机器学习水果识别

刚接触机器学习时候写的了,当时只知道机器学习不知道深度学习还以为只能人为的提取特征根据特征训练,后来才发现有深度学习这样更好的选择可以自动提取特征值。除了特征,深度学习在复杂背景下的效果也会明显优于普通机器学习,所以还是建议使用深度学习的方法。2019.4.25

一、用python+opencv实现物体特征值提取

以水果为例。要用机器学习来实现水果识别,无论是训练还是识别阶段都需要提取图片中水果的特征值。本篇将讲述如何提取水果的周长面积颜色长度宽度7个特征值。

1、读取图像、转为灰度图像并降噪

from math import *import cv2 as cvimport numpy as npimg = cv.imread(path)gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)blurred = cv.GaussianBlur(gray, (3, 3), 0)

2、获取水果轮廓

这里使用图像梯度的方法

xgrad = cv.Sobel(blurred, cv.CV_16SC1, 1, 0)ygrad = cv.Sobel(blurred, cv.CV_16SC1, 0, 1)edge_output = cv.Canny(xgrad, ygrad, 50, 150)cloneImg, contours, heriachy = cv.findContours(edge_output, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

cv.findContours将图片中识别到的轮廓返回给contours变量,contours是一个list类型数据,里面存放了识别到的所有轮廓。有时候并不能很好的将目标轮廓完整的识别出来或者有没有去除掉的噪点的干扰所以不能简单粗暴的将获取到的轮廓全部运用。我尝试了一下两种方法:

将最大轮廓画入最开始的img图像并显示

max = 0maxA = 0for i, contour in enumerate(contours):    x, y, w, h = cv.boundingRect(contour)    if w*h>maxA:    	max=i    	maxA=w*hcv.drawContours(img, contours, max, (0, 0, 255), 2)#画框x, y, w, h = cv.boundingRect(contours[max])img = cv.rectangle(img, (x, y), (x + w, y + h), (0, 255,  0), 2)cv.imshow('img', img)

结果如图:

这个方法有一个问题:如果目标物体的轮廓被分为了多个区域,则不能完全显示出来轮廓。
所以想到了另一个方法:

将小于某一规模的轮廓删除

num=[]for i, contour in enumerate(contours):	x, y, w, h = cv.boundingRect(contour)	if w < 50 or h < 50:        continue    num.append(i)for i in num:	if i == 0:		continue	contours[0] = np.concatenate((contours[i], contours[0]))cv.drawContours(img, contours, max, (0, 0, 255), 2)#画框x, y, w, h = cv.boundingRect(contours[0])img = cv.rectangle(img, (x, y), (x + w, y + h), (0, 255,  0), 2)cv.imshow('img', img)


这个方法可以去除噪点的影响并且将轮廓连接起来。虽然轮廓也不正确但是矩形框是正确的。
轮廓可以通过cv2.contourArea和cv2.arcLength(cnt,True)分别获取面积和周长,但是因为轮廓是错误的,面积和周长求出来是不正确的。但是通过画出来的矩形框可以明显看出第二种方法是优于第一种方法的,所以我们要另找方法来获得周长和面积。到这里,已经可以拿到水果的长和宽了:

length = 0width = 0if w > h:    length = w    width = helse:    length = h    width = w

3、提取水果的面积周长及颜色

为了提取面积和周长,这里分别再产生二值图和二值图的边缘提取图
###尽可能消除环境噪点的影响
将要用到的图像先剪裁出刚才识别到的区域,减小背景对识别影响的可能性

def myCut(img, x, y, w, h):    cut = img[y:y + h, x:x + w]    cv.imshow("cut", cut)    return cutcut_img = myCut(img, x, y, w, h)cut_blurred = myCut(blurred, x, y, w, h)

获取二值图并计算面积

def GetArea(img):    count = 0    point_y = []    point_x = []    height, width = img.shape    for h in range(0, height, 1):        for w in range(0, width, 1):            if (img[h, w] == 0):                count += 1                point_y.append(h)                point_x.append(w)    return count, point_x, point_yret, binary = cv.threshold(cut_blurred, 70, 255, cv.THRESH_BINARY)cv.imshow("bi", binary)  # 求面积area, point_x, point_y = GetArea(binary)

其中point_x、point_y分别记录着面积的区域,之后求颜色需要用到。

提取边缘并计算周长

def GetCircumference(img):    count = 0    height, width = img.shape    for h in range(0, height, 1):        for w in range(0, width, 1):            if (img[h, w] == 255):                count += 1    return countedge = cv.Canny(binary, 40, 100)cv.imshow("edge", edge)  # 求周长circumference = GetCircumference(edge)

提取平均颜色

def GetColor(img, point_height, point_width):    R = 0    G = 0    B = 0    count = 0    color = []    for i in range(0, len(point_height), 1):        count += 1        R += img[point_height[i], point_width[i]][0]        G += img[point_height[i], point_width[i]][1]        B += img[point_height[i], point_width[i]][2]    R = int(R / count)    G = int(G / count)    B = int(B / count)    color.append(R)    color.append(G)    color.append(B)    return colorcolor = GetColor(cut_img, point_height, point_width)#打印刚才所求的面积周长及颜色print('area:', area, 'circumference:', circumference, 'longth:', longth, 'width:', width, 'color:', color)

二、代码

#!usr/env/bin python3from math import *import cv2 as cvimport numpy as npfile = '/Users/apple/Desktop/video/image-1/'p=file+'data.txt'#f = open(p, 'a')def myCut(img, x, y, w, h):    cut = img[y:y + h, x:x + w]    cv.imshow("cut", cut)    return cutdef GetColor(img, point_height, point_width):    R = 0    G = 0    B = 0    count = 0    color = []    for i in range(0, len(point_height), 1):        count += 1        R += img[point_height[i], point_width[i]][0]        G += img[point_height[i], point_width[i]][1]        B += img[point_height[i], point_width[i]][2]    R = int(R / count)    G = int(G / count)    B = int(B / count)    color.append(R)    color.append(G)    color.append(B)    return color# 返回面积def GetArea(img):    count = 0    point_height = []    point_width = []    height, width = img.shape    for h in range(0, height, 1):        for w in range(0, width, 1):            if (img[h, w] == 0):                count += 1                point_height.append(h)                point_width.append(w)    return count, point_width, point_height# 返回周长def GetCircumference(img):    count = 0    height, width = img.shape    for h in range(0, height, 1):        for w in range(0, width, 1):            if (img[h, w] == 255):                count += 1    return countdef edge(img):    # 灰度图像    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)    # 高斯模糊,降低噪声    blurred = cv.GaussianBlur(gray, (3, 3), 0)    # 图像梯度    xgrad = cv.Sobel(blurred, cv.CV_16SC1, 1, 0)    ygrad = cv.Sobel(blurred, cv.CV_16SC1, 0, 1)    # 计算边缘    # 50和150参数必须符合1:3或者1:2    edge_output = cv.Canny(xgrad, ygrad, 50, 150)    cloneImg, contours, heriachy = cv.findContours(edge_output, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)    # max = 0    # maxA = 0    num = []    for i, contour in enumerate(contours):        x, y, w, h = cv.boundingRect(contour)        # if (w * h > maxA):        #     max = i        #     maxA = w * h        if w < 50 or h < 50:            continue        num.append(i)    for i in num:        # cv.drawContours(img, contours, i, (0, 0, 255), 2)        # x, y, w, h = cv.boundingRect(contours[i])        # img = cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)        if i == 0:            continue        contours[0] = np.concatenate((contours[i], contours[0]))    cv.imshow('img', img)    x, y, w, h = cv.boundingRect(contours[0])    cut_img = myCut(img, x, y, w, h)    cut_blurred = myCut(blurred, x, y, w, h)    cv.imshow('cut', cut_blurred)    ret, binary = cv.threshold(cut_blurred, 70, 255, cv.THRESH_BINARY)    cv.imshow("bi", binary)  # 求面积    edge = cv.Canny(binary, 40, 100)    cv.imshow("edge", edge)  # 求周长    longth = 0    width = 0    if w > h:        longth = w        width = h    else:        longth = h        width = w    area, point_width, point_height = GetArea(binary)    circumference = GetCircumference(edge)    color = GetColor(cut_img, point_height, point_width)    print('area:', area, 'circumference:', circumference, 'longth:', longth, 'width:', width, 'color:', color)    # f.write(str(area))    # f.write(' ')    # f.write(str(circumference))    # f.write(' ')    # f.write(str(longth))    # f.write(' ')    # f.write(str(width))    # f.write(' ')    # for i in range(3):    #     f.write(str(color[i]))    #     f.write(' ')    # f.write('\n')def do():    for i in range(1, 8, 1):        print(i, ':')        path = file + str(i) + '.jpg'        src1 = cv.imread(path)        # 图三(原图)        size = src1.shape        src = cv.resize(src1, ((int)(size[1] / 5), (int)(size[0] / 5)), cv.INTER_LINEAR)        edge(src)        cv.waitKey(0)    cv.destroyAllWindows()    #f.closed()do()
1 :area: 7032 circumference: 605 longth: 183 width: 177 color: [34, 31, 35]2 :area: 8564 circumference: 619 longth: 206 width: 197 color: [34, 29, 32]3 :area: 9032 circumference: 623 longth: 221 width: 215 color: [44, 36, 37]4 :area: 9121 circumference: 630 longth: 232 width: 214 color: [44, 37, 38]5 :area: 10747 circumference: 714 longth: 224 width: 216 color: [43, 36, 40]6 :area: 9127 circumference: 630 longth: 196 width: 194 color: [44, 39, 44]7 :area: 9787 circumference: 636 longth: 198 width: 198 color: [46, 41, 47]
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
OpenCV探索之路(二十二):制作一个类“全能扫描王”的简易扫描软件
如何获得物体的主要方向?
基于distanceTransform-距离变换的区域中心提取
OpenCV图像处理教程C++(二十)轮廓发现、凸包、轮廓周围绘制圆和矩形
opencv 车牌定位及分割
OpenCV-计算轮廓面积cv::contourArea
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服