OpenCV对图片中的水果进行识别计算其面积长度等

本项目所用到的技术有:

OpenCV

Python的一些库:sys,openpyxl,numpy,PyQt5,PIL

本文可以做一些课程设计的项目

本文为作者原创,转载请注明出处,如果需要完整的代码,可以关注我私信

上面是用到的样例图片,一张小青桔

首先对小青桔进行图像的矫正,利用仿射变化找M矩阵

python 复制代码
import numpy as np
import cv2
import math
import matplotlib.pyplot as plt
import pandas as pd
 
def get4points(img: np.ndarray, thed, n):
    # 灰度和二值化
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, binary = cv2.threshold(gray, thed, 255, cv2.THRESH_BINARY)
    # 搜索轮廓
    contours, hierarchy = cv2.findContours(
        binary,
        cv2.RETR_LIST,
        cv2.CHAIN_APPROX_SIMPLE)
    
    len_list = []
    for i in range(len(contours)):
        len_list.append(len(contours[i]))    
    sy = np.argsort(np.array(len_list))[-n]
    # 寻找顶点
    sum_list = []
    dif_list = []
    for i in contours[sy]:
        sum = i[0][0]+i[0][1]
        sum_list.append(sum)
        dif_list.append(i[0][0]-i[0][1])
 
    id_lb = np.argsort(np.array(sum_list))
    id_lb2 = np.argsort(np.array(dif_list))
    lu_id , rd_id = id_lb[0], id_lb[-1]
    ld_id , ru_id = id_lb2[0], id_lb2[-1]
    points = np.array([contours[sy][lu_id][0], contours[sy][rd_id][0],
                       contours[sy][ld_id][0], contours[sy][ru_id][0]])
    return points, contours, sy
def order_points(pts):
    # 初始化坐标点
    rect = np.zeros((4, 2), dtype = "float32")
    # 获取左上角和右下角坐标点
    s = pts.sum(axis = 1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    # 分别计算左上角和右下角的离散差值
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect
 
 
def four_point_transform(image, pts):
    # 获取坐标点,并将它们分离开来
    rect = order_points(pts)
    (tl, tr, br, bl) = rect
    # 计算新图片的宽度值,选取水平差值的最大值
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))
    # 计算新图片的高度值,选取垂直差值的最大值
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))
    # 构建新图片的4个坐标点
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype="float32")
    # 获取仿射变换矩阵并应用它
    M = cv2.getPerspectiveTransform(rect, dst)
    # 进行仿射变换
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    # 返回变换后的结果
    return warped
 
def show_cmp_img(original_img, transform_img):
    _, axes = plt.subplots(1, 2)
    # 显示图像
    axes[0].imshow(original_img)
    axes[1].imshow(transform_img)
    # 设置子标题
    axes[0].set_title("original image")
    axes[1].set_title("transform image")
    plt.show() 

 # 读取图片
image = cv2.imread('D:/Pythonstudy/deeplearning/picture/8.jpg')
points, _, _ = get4points(image, 127, 1)
# 获取原始的坐标点
pts = np.array(points, dtype="float32")
# 对原始图片进行变换
warped = four_point_transform(image, pts)
show_cmp_img(image, warped)

现在对图片进行形态学处理,利用腐蚀,膨胀得到小青桔

python 复制代码
# 灰度图
gray_img = cv2.cvtColor(warped,cv2.COLOR_BGR2GRAY)
# 高斯
gauss_img = cv2.GaussianBlur(gray_img,(7,7),1.4)
# 二值图
ret,thresh1 = cv2.threshold(gauss_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
kernel = np.ones((5,5),np.uint8)
# 腐蚀膨胀
erode = cv2.dilate(thresh1,kernel,iterations = 17)
erode = cv2.erode(erode,kernel,iterations = 13)
# 边缘检测
v1 = cv2.Canny(erode,ret/2,ret)

找到所有的轮廓

python 复制代码
contours,hierarchy = cv2.findContours(v1, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) 

画出所有轮廓的外接矩阵

python 复制代码
test_img = warped.copy()
contour_area_dict = {}
rect_area = list()
for i in range(len(contours)):
    x,y,w,h = cv2.boundingRect(contours[i])
    area = w*h
    rect_area.append(area)
    cv2.rectangle(test_img,(x,y),(x+w,y+h),(255,0,0),3)
    contour_area_dict[i]=area
max_contour_ori = max(contour_area_dict,key = contour_area_dict.get)
print(rect_area)
print(contour_area_dict)
print(max_contour_ori)
plt.imshow(test_img)

利用圆形度+最大面积两种方法结合找到位置

对这一部分进行解释:首先比较轮廓与圆的相似度,认为接近圆的就是小青桔,然后对这个轮廓的面积进行判断,如果其过于小(小于四周正方形的面积)则认为这个轮廓不对,找错了位置,此时利用最大面积求解(所有轮廓的面积最大的就认为是小青桔)

python 复制代码
# 容差
circularity_threshold = 0.5
img= warped.copy()
yuan_contour_list  = list()
for contour in contours:  
    # 计算轮廓的面积和周长  
    area = cv2.contourArea(contour) 
    print(area)
    perimeter = cv2.arcLength(contour, True)    
    # 计算圆形度,注意这里乘以4*np.pi是为了归一化  
    circularity = (4 * np.pi * area) / (perimeter ** 2)   
    # 筛选圆形度接近1的轮廓  
    if abs(1 - circularity) < circularity_threshold: 
        print(cv2.contourArea(contour))
        yuan_contour_list.append(contour)
python 复制代码
print("接近圆形的个数%d"%len(yuan_contour_list))
test_2 = cv2.drawContours(warped.copy(),yuan_contour_list , -1, (0, 255, 0), 4)
plt.imshow(test_2)
python 复制代码
max_area = yuan_contour_list[0]
for i in yuan_contour_list:
    if(cv2.contourArea(i) > cv2.contourArea(max_area)):
        max_area = i
print(cv2.contourArea(max_area))
python 复制代码
if(cv2.contourArea(max_area)<117899):
    max_area = contours[max_contour_ori]

确定之后画出外接矩形

python 复制代码
cv2.drawContours(img, [max_area], -1, (0, 255, 0), 2)
x,y,w,h = cv2.boundingRect(max_area)
img_wj = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),3)
plt.imshow(img_wj)


此时基本的代码已经完成,然后对代码进行设计,设计可视化的窗口




由于篇幅限制,可视化界面的代码没有贴上来,如果有需要的可以关注后找我要,可以直接私信。

相关推荐
奔跑中的小象1 小时前
统信UOS + 天数AI卡部署SGLang服务手册
人工智能·uos·sglang·天数智芯
DevSecOps选型指南1 小时前
中国版Mythos,为何是悬镜安全灵脉CodeAI?
人工智能·安全
Shockang1 小时前
LangGraph 状态机实战
人工智能
DLYSB_2 小时前
存储运维实战:基于 Ceph Event 监听与 Python 适配器的分布式存储健康度物理声光响应架构
运维·ceph·python·报警灯
刹那芳华19922 小时前
循环神经网络的从零开始实现(RNN)
人工智能·rnn·深度学习
阿童木写作2 小时前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
科技之门2 小时前
AI3D从建模到贴图、绑骨和动画的完整流程怎么做?V2Fun完整工作流指南
人工智能·3d·贴图
宇宙第一小趴菜2 小时前
二、机器学习的应用领域和发展史
人工智能·机器学习
前端开发江鸟2 小时前
我写过 MCP Server,却一直以为 MCP 只有 Tool
人工智能
天国梦2 小时前
自习室智能化升级避坑指南:天学网AI智习室方案实测与选型建议
大数据·人工智能