使用阈值分割测量叶片面积

前言

在农学实验或者作物模型中,lai是一个非常重要的参数。lai = 叶片总面积/种植密度
这里介绍使用扫描仪或手机拍照计算叶片总面积的方法。

我在这里提供两个演示:
1.使用扫描仪的图片来计算叶片面积
2.使用手机拍照的图片来计算叶片面积,但要求有背景板,且背景板的大小已知

两种方式的照片均不能有太多的噪点

示例1:扫描仪扫描的图片(300ppi)
在这里插入图片描述

示例2:拍照的图片
在这里插入图片描述

使用阈值分割程序确定阈值

这里介绍一下阈值分割程序的使用

import cv2
import numpy as np
filepath = r'E:\reco_lai_for_zeng\img996.jpg'
frameWidth = 800
frameHeight = 480
cap = cv2.imread(filepath)



def empty(a):
    pass


cv2.namedWindow("HSV")
cv2.resizeWindow("HSV", 640, 240)
cv2.createTrackbar("HUE Min", "HSV", 0, 179, empty)
cv2.createTrackbar("HUE Max", "HSV", 179, 179, empty)
cv2.createTrackbar("SAT Min", "HSV", 0, 255, empty)
cv2.createTrackbar("SAT Max", "HSV", 255, 255, empty)
cv2.createTrackbar("VALUE Min", "HSV", 0, 255, empty)
cv2.createTrackbar("VALUE Max", "HSV", 255, 255, empty)

while True:

    img = cap
    imgHsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

    h_min = cv2.getTrackbarPos("HUE Min", "HSV")
    h_max = cv2.getTrackbarPos("HUE Max", "HSV")
    s_min = cv2.getTrackbarPos("SAT Min", "HSV")
    s_max = cv2.getTrackbarPos("SAT Max", "HSV")
    v_min = cv2.getTrackbarPos("VALUE Min", "HSV")
    v_max = cv2.getTrackbarPos("VALUE Max", "HSV")
    print(h_min)

    lower = np.array([h_min, s_min, v_min])
    upper = np.array([h_max, s_max, v_max])
    mask = cv2.inRange(imgHsv, lower, upper)
    result = cv2.bitwise_and(img, img, mask=mask)

    mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
    hStack = np.hstack([img, mask, result])
    # cv2.imshow('Original', img)
    # cv2.imshow('HSV Color Space', imgHsv)
    # cv2.imshow('Mask', mask)
    # cv2.imshow('Result', result)
    cv2.namedWindow("Horizontal Stacking", 0)
    cv2.resizeWindow("Horizontal Stacking", 1200, 600)
    cv2.imshow('Horizontal Stacking', hStack)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

第一种阈值分割

运行之后,调整HSV色彩空间的阈值,使其能够分离叶片与背景

分别是原始图片、mask、result

mask:把取的阈值中间的值变成255(0是黑,255是白)
result:使用掩膜图像白色区域是保留处理图像像素,黑色区域是对需要处理图像像素的剔除

注意,这里叶片的范围是白色的,所以在这里,我们取到的阈值是叶片的颜色范围

在这里插入图片描述
那么我们得到的阈值是
lower = [36,35,0]
upper = [179,255,255]

第二种阈值分割

在这里插入图片描述

在这里插入图片描述
注意,这里叶片的范围是黑色的,所以在这里,我们取到的阈值是叶片以外的颜色范围

这时候,我们得到的阈值是:
lower = [0,0,214]
upper = [179,42,255]

(当然,这幅图片也可以用第一种提取阈值的方法呀)

在这里插入图片描述

在这里插入图片描述
这时候,我们得到的阈值是:
lower = [29,43,0]
upper = [54,255,255]

提取叶面积

提取叶面积主要是有两点要注意:

  • 分清楚阈值取得是叶片还是叶片以外的区域

  • 分清楚是扫描仪还是拍照获取得图片

  • 当使用扫描仪时,每个像素的实际大小是固定的。(因为可以自己设置ppi)

  • 当拍照时,需要根据叶片像素数量和整幅图片像素数量的比值确定叶片面积;所以拍照的图片要先裁剪至背景板大小

根据实际情况自行修改代码:

在代码中,如果输入的阈值是叶片阈值,

colored = len(imgray[imgray == 0])

要修改为

colored = total - len(imgray[imgray == 0])

若是叶片以外范围的阈值,则保持为

colored = len(imgray[imgray == 0])

也可以根据实际情况修改ppi的值

扫描仪对应的叶面积提取

这里使用的阈值是叶片阈值

import pandas as pd
import numpy as np
import cv2

im = cv2.imread(r'E:\reco_lai_for_zeng\img996.jpg')
img_source = cv.imread(file_path)  # 读取图像文件
ji = img_source.size
hsv = cv.cvtColor(img_source, cv.COLOR_BGR2HSV)
lower_green = np.array([36,24,0])
upper_green = np.array([74,255, 105])
# 设置HSV的阈值使得只取绿色
mask = cv.inRange(hsv, lower_green, upper_green)
# 将掩膜和图像逐像素相加
res = cv.bitwise_and(img_source, img_source, mask=mask)
si = res.size
imgray = cv.cvtColor(res, cv.COLOR_BGR2GRAY)
total = imgray.size
colored = total - len(imgray[imgray == 0])
lai = colored * 25.4 * 25.4 / (3000 * 3000)
print(lai)

得到(单位:cm^2)

C:\Users\91373\anaconda3\python.exe E:/reco_lai_for_zeng/16.py
129.72361152
Process finished with exit code 0

拍照对应的叶面积提取

这里使用的阈值是叶片范围以外的阈值

这里多了一步,设置背景板大小(单位:cm)
这里设置的单位是啥,输出的单位就是啥

background_real_area= 45*140
import pandas as pd
import numpy as np
import cv2

background_real_area= 45*140


im = cv2.imread(r'E:\reco_lai_for_zeng\20210312112247.png')
img_source = im
ji = img_source.size
hsv = cv2.cvtColor(img_source, cv2.COLOR_BGR2HSV)
lower_green = np.array([36,35,0])
upper_green = np.array([179,255, 255])
mask = cv2.inRange(hsv, lower_green, upper_green)
res = cv2.bitwise_and(img_source, img_source, mask=mask)
si = res.size
imgray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
total = imgray.size
colored = len(imgray[imgray == 0])
lai = colored * background_real_area / total
print(lai)

C:\Users\91373\anaconda3\python.exe E:/reco_lai_for_zeng/shibie.py
2705.567262837485
Process finished with exit code 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值