刚接触机器学习时候写的了,当时只知道机器学习不知道深度学习还以为只能人为的提取特征根据特征训练,后来才发现有深度学习这样更好的选择可以自动提取特征值。除了特征,深度学习在复杂背景下的效果也会明显优于普通机器学习,所以还是建议使用深度学习的方法。2019.4.25
以水果为例。要用机器学习来实现水果识别,无论是训练还是识别阶段都需要提取图片中水果的特征值。本篇将讲述如何提取水果的周长、面积、颜色、长度、宽度7个特征值。
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)
这里使用图像梯度的方法
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类型数据,里面存放了识别到的所有轮廓。有时候并不能很好的将目标轮廓完整的识别出来或者有没有去除掉的噪点的干扰所以不能简单粗暴的将获取到的轮廓全部运用。我尝试了一下两种方法:
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)
length = 0width = 0if w > h: length = w width = helse: length = h width = w
为了提取面积和周长,这里分别再产生二值图和二值图的边缘提取图
###尽可能消除环境噪点的影响
将要用到的图像先剪裁出刚才识别到的区域,减小背景对识别影响的可能性
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]
联系客服