水果检测与自动识别分级:图像处理技术及颜色模型分析
水果检测与自动识别分级:1,对于图像的灰度处理,二值化 2,边缘检测,特征提取,中值滤波 对于水果的分级,包括对水果的用颜色模型进行分析处理
上周在社区超市兼职帮理货员姐姐理了三小时柑橘,指甲缝卡得全是橙皮油,最后挑出的大小均匀色泽又鲜亮的还没一小筐——分拣机要是能普及到这种夫妻老婆店就好了!但分拣机背后的核心其实就是几步我们普通人用Python OpenCV就能捣鼓出来的操作:先把水果从背景“揪出来”,再“看清楚”它的形状大小有没有疤,最后“摸准”(用算法算啦)颜色够不够卖相。
今天就拆开来唠唠这几步,中间混点小代码,大家要是有兴趣可以找家里纯色盘子上的苹果橘子拍个照试试玩。
第一步:先把“多余的背景噪声”扫干净——灰度处理、二值化、中值滤波
首先拿到一张手机拍的彩色图,OpenCV默认读进来是BGR三通道的(划个小重点,不是我们更熟的RGB哦,后期要转RGB才会看到正常颜色预览)。这三个通道每个像素都有256种取值,信息太杂太乱了,就像你找东西的时候桌面上全是碎纸——先把彩色图简化成“灰度黑白照”(信息只剩1个通道,只有亮暗区别,没有色彩),桌面干净一半!
import cv2
import numpy as np
img = cv2.imread('apple_test.jpg')
# OpenCV默认读BGR,先转成RGB存个副本,后面显示颜色方便
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 转灰度!
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 先看看效果对比(怕AI太啰嗦,直接用cv2的简单窗口展示就行)
cv2.imshow('原图BGR(可能有点奇怪)', img)
cv2.imshow('灰度版', gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
接下来是“扫桌面碎纸渣”——中值滤波。有时候拍照片手抖或者盘子有小灰尘,灰度图里会有很多小噪点,边缘检测的时候会识别成乱七八糟的线。中值滤波就像用“取周围像素中位数”的小刷子,把这些小噪点磨掉,又不会把水果的轮廓磨糊(这点比高斯滤波好多了,高斯会把边缘柔化得像加了美颜磨皮)。
然后就是“把水果和盘子彻底分开”——二值化。简单来说就是设定一个“亮度门槛”:比门槛亮的像素全变成白色(255),比门槛暗的全变成黑色(0)。像我选的这个纯白背景红富士,背景亮暗都差不多在240以上,苹果果肉果核暗一些,门槛设成220左右就行。如果背景不是纯色的,后面还可以补自适应阈值,但纯色背景先玩明白全局的~
# 中值滤波,ksize选3或者5就行,3磨小渣,5磨稍大一点的
blur = cv2.medianBlur(gray, 3)
# 全局二值化,这里我试了试220的门槛,效果还不错
ret, binary = cv2.threshold(blur, 220, 255, cv2.THRESH_BINARY_INV)
# 这里加了个_INV!因为红富士暗背景亮,默认的BINARY是亮变白暗变黑,我们要水果主体变白,所以反过来
# 展示磨完噪点的图和二值化后的“黑白剪影”
cv2.imshow('磨完噪点的灰度', blur)
cv2.imshow('黑白剪影', binary)
cv2.waitKey(0)
cv2.destroyAllWindows()
第二步:“看清楚”水果长啥样——边缘检测、特征提取
剪影出来了,接下来要“勾出水果的轮廓”(边缘检测),然后用轮廓算它的面积、周长、圆度——圆度高的大概率是好苹果(没烂没被挤变形),面积周长对应大小。
水果检测与自动识别分级:1,对于图像的灰度处理,二值化 2,边缘检测,特征提取,中值滤波 对于水果的分级,包括对水果的用颜色模型进行分析处理
边缘检测我用Canny吧,这个是经典中的经典,检测出来的轮廓细而且准,就像画画用的勾线笔。Canny需要两个参数:低阈值和高阈值,低于低阈值的边缘直接扔掉,高于高阈值的直接保留,中间的如果连到高阈值的边缘也保留,一般取1:2或者1:3的比例就行,比如30和60。
# Canny边缘检测
edges = cv2.Canny(binary, 30, 60)
# 找轮廓!这里的cv2.RETR_EXTERNAL只找最外层的轮廓(水果边缘),忽略内部果核啥的小轮廓
contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 先把轮廓画在RGB原图上看看准不准
# copy一份原图,避免破坏原始数据
contour_img = img_rgb.copy()
# contours[0]就是我们的苹果轮廓,因为只有一个水果嘛,颜色用红色(0,255,0?哦不对,RGB是(255,0,0),厚度选2
cv2.drawContours(contour_img, contours, 0, (255, 0, 0), 2)
# 展示边缘图和画了轮廓的原图
cv2.imshow('Canny边缘', edges)
cv2.imshow('勾了轮廓的苹果', cv2.cvtColor(contour_img, cv2.COLOR_RGB2BGR)) # 转BGR给cv2显示
cv2.waitKey(0)
cv2.destroyAllWindows()
勾准了轮廓就来算特征!先算面积(像素面积,后期可以通过对比参照物比如硬币的像素面积换算成实际平方厘米),再算周长,最后算圆度=4π*面积/(周长²)——完美的圆圆度是1,一般超市卖的红富士圆度能到0.8以上,烂掉的挤扁的会掉到0.7以下。
# 轮廓[0]的面积
area = cv2.contourArea(contours[0])
# 轮廓[0]的周长,True表示是闭合轮廓
perimeter = cv2.arcLength(contours[0], True)
# 圆度
roundness = 4 * np.pi * area / (perimeter ** 2)
print(f"这个苹果的像素面积是:{area}")
print(f"像素周长是:{perimeter:.2f}")
print(f"圆度是:{roundness:.2f}")
我用的那张图圆度大概是0.87,卖相还不错~
第三步:“摸准”颜色够不够格——颜色模型分析
形状大小没问题了,最后就是颜色了!不能用BGR或者RGB来分析,因为这两个颜色模型受光照影响太大了——比如同一个苹果在太阳下拍和在超市灯光下拍,RGB数值差很多。
要用HSV颜色模型!这个模型把颜色分成了H(色相,0-180,代表是什么颜色:红是0-10和170-180,橙是11-25,绿是35-77,黄是26-34)、S(饱和度,0-255,代表颜色纯不纯:0是灰色,255是最鲜艳的)、V(明度,0-255,代表亮不亮:0是黑,255是白)三个部分,我们只需要关注H和S就行,V可以稍微忽略或者做个小范围过滤,受光照影响就小多啦!
比如挑红富士,我们要选H在0-10和170-180之间,S在80-255之间(饱和度够高,不是那种淡红)的区域占比大的苹果。
# 先把RGB转成HSV
hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)
# 红富士有两个红色区间:低红(0-10)和高红(170-180),分别做掩膜
lower_red1 = np.array([0, 80, 50]) # 这里V留了50以上,避免太暗的阴影区域干扰
upper_red1 = np.array([10, 255, 255])
mask1 = cv2.inRange(hsv, lower_red1, upper_red1)
lower_red2 = np.array([170, 80, 50])
upper_red2 = np.array([180, 255, 255])
mask2 = cv2.inRange(hsv, lower_red2, upper_red2)
# 把两个掩膜合起来
mask = cv2.bitwise_or(mask1, mask2)
# 把掩膜和二值化的水果剪影再合一次!只统计水果区域内的红色像素,避免背景干扰
final_mask = cv2.bitwise_and(mask, binary)
# 统计红色区域像素数
red_pixels = cv2.countNonZero(final_mask)
# 统计水果总像素数(就是之前的轮廓面积)
total_pixels = area
# 红色占比
red_ratio = red_pixels / total_pixels
print(f"这个苹果的红色区域占比是:{red_ratio:.2%}")
# 展示一下最终的红色区域掩膜
cv2.imshow('只保留红富士区域的掩膜', final_mask)
cv2.waitKey(0)
cv2.destroyAllWindows()
我用的那张图红色占比大概是78%,已经算是一级果啦!一般来说夫妻老婆店卖的红富士红色占比50%以上就行,超市精品区要70%以上。
好了,捣鼓到这里,一台“迷你简易版水果分拣机”的核心算法就差不多了!把面积、圆度、红色占比这三个指标结合起来,设个阈值,就能自动把水果分成一级、二级、三级甚至淘汰品啦~虽然没法和工业级的比,但自己在家玩玩,给夫妻老婆店提个小思路还是没问题的!

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)