基于OpenCV实现玉米排种株距检测

概述

基于opencv实现玉米排种株距检测,从而对排种器排种性能进行检测;

实现原理

1.调用摄像头
2.识别到种子,并记录当前时间
3.获取两次识别到种子的时间戳
4.由 传送带速度 * 两粒种子时间间隔 = 株距,得出株距
5.硬件:JPS-12试验台(传送带)、电脑、摄像头、排种器
在这里插入图片描述

完整代码

"""
1.调用摄像头
2.识别种子,并记录当前时间
3.获取两次识别到种子的时间戳
4.由传送带速度,计算出株距
author : 南栀北辰
Q:1761630764
start_date :2022-11-08
end_date :2022-11-12
"""
# 加载库
import cv2
import cv2 as cv
import numpy as np
import time
from matplotlib import pyplot as plt

# 定义调参变量
Speed = 3.3  # 传送带速度,单位 : m/s
Distance = []  # 种子间距, 单位: m
W_multiple = 1  # 摄像头捕捉的宽度倍数,大于1放大捕捉范围,小于1缩小捕捉范围
H_multiple = 1  # 摄像头捕捉的长度倍数,大于1放大捕捉范围,小于1缩小捕捉范围
Interval = 10  # 每间隔 interval ms,捕捉一帧
Appear_time = []  # 临时变量,存储每次种子出现的时间戳
Sowing_time = []  # 种子间隔时间 s

# 临时变量
time1 = []  # 临时变量,每一次黑白变化清空一次


# 获取时间函数  单位s,小数点后6位有效数据
def get_time():
    # noinspection PyShadowingNames
    use_time = time.time()
    # print("时间戳 :", time_stamp)  # 秒级
    # print(int(round(time_stamp * 1000)))  # 毫秒级
    return use_time


# 写入文本函数
def save_write(path, mode, content):
    file = open(path, mode)  # 打开现有文件,或创建文件
    file.write(content)  # 写入内容
    content = file.readlines()  # 读出内容
    file.close()
    return content


# 1.调用摄像头
camera = cv2.VideoCapture(0, cv2.CAP_DSHOW)  # 摄像头
# cap = cv2.VideoCapture('F:/Python_Learn_Source/02.OpenCV_DATE/English.mp4')
width, height = camera.get(3), camera.get(4)  # 获取摄像头的宽和高

# 以原分辨率的一倍来捕获,用来该改变摄像头捕捉的范围,
camera.set(cv.CAP_PROP_FRAME_WIDTH, width * W_multiple)
camera.set(cv.CAP_PROP_FRAME_HEIGHT, height * H_multiple)

history = 300  # 用于训练背景的帧数,默认为500帧,如果不手动设置learningRate,history就被用于计算当前的learningRate,此时history越大,learningRate越小,背景更新越慢;
learningRate = 0  # 值为0-1,为0时背景不更新,为1时逐帧更新,默认为-1,即算法自动更新;
varThreshold = 70  # 用于判断当前像素是前景还是背景。一般默认16,如果光照变化明显,如阳光下的水面,建议设为25,36,具体去试一下也不是很麻烦,值越大,灵敏度越低;
mog = cv2.createBackgroundSubtractorMOG2(history=history, detectShadows=False, varThreshold=varThreshold)  # 应用MOG2模型
se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))  # 构造全是1的扫描核,用于形态学操作

time.sleep(0.5)
# 2.判断是否读取成功
while camera.isOpened():
    # 3.获取每一帧图像
    success, img = camera.read()  # 从摄像头读取照片
    # 4.获取成功显示图像
    if success:
        cv2.imshow('frame', img)
        fg_mark = mog.apply(img)  # 对图像进行混合高斯模型
        cv2.imshow('fg_mark', fg_mark)
        ret, thresh = cv.threshold(fg_mark, 0, 250, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
        # binary = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, se)
        bg_image = mog.getBackgroundImage()  # 背景图像
        cv2.imshow('bg_image', bg_image)
        contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
        # contours, hierarchy = cv.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
        print('轮廓个数为', len(contours))  # 轮廓个数
        # print(hierarchy)
        # print(len(contours[0]))  # 轮廓包含多少像素点
        # cnt = contours[0]  # 第几个轮廓
        cv.drawContours(img, contours, -1, (0, 255, 0), 1)
        cv.imshow("frame", img)
        # 4.1判断轮廓个数,有种子轮廓层次总数为2
        # if len(contours) == 1 or len(contours) == 2 or len(contours) == 3 or len(contours) == 4:  # 获取当前时间,给时间变量1
        if (len(contours) >= 8) and (len(contours) <= 30000):   # 获取当前时间,给时间变量1
            use_time = get_time()
            time1.append(use_time)
            # print(time1)
            # time1[0]
        else:  # 将time1[0]先写入Appear_time = []保存,再进行清空time1列表
            if len(time1) != 0:
                Appear_time.append(time1[0])  # 写入time1[0]
                print("种子每出现一次的时间戳", Appear_time)
                time1.clear()  # 对列表清空

    # 5.每间隔 interval ms,捕捉一帧
    if cv.waitKey(Interval) & 0xFF == ord('0'):  # 按下数字0 ,关闭摄像头
        break

print('.................数据采集完毕,进行数据处理中..................')
# 6.利用时间戳和传送带的速度计算株距,并保存在“株距.txt”文件中
# 6.1 计算种子间隔时间,并记录在文本 ‘播种间隔时间.txt’中
# print(len(Appear_time))
for i in range(len(Appear_time)):
    if i == (len(Appear_time)-1):
        break
    else:
        D_value = Appear_time[i+1] - Appear_time[i]  # 相邻种子间的时间差
        Sowing_time.append(D_value)

save_write('播种间隔时间.txt', 'w+', str(Sowing_time))


# 6.2 计算株距,并记录到文本‘株距.txt’
for j in range(len(Sowing_time)):
    Jian_Ju = Sowing_time[j] * Speed
    Distance.append(Jian_Ju)

save_write('株距.txt', 'w+', str(Distance))

print('...................数据处理和保存完成..........................')

for t in range(3):
    print(f'{3-t}秒后程序结束')
    time.sleep(1)

print('程序结束')
# 7.释放视频对象
camera.release()  # 关闭摄像头
cv.destroyAllWindows()  # 销毁进程

检测结果

在这里插入图片描述

问题

由于排种过程中,玉米和传送带会发生碰撞回弹,导致少量数据明显异常,去除明显异常数据即可;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

南栀北辰SDN

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

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

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

打赏作者

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

抵扣说明:

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

余额充值