项目简介 |
实习方法 |
源码分享 |
项目简介:
利用python自带的opencv库来计算植物叶片的叶面积、叶直径和叶周长,拍摄图片就可以直接得到真实的叶面积、叶直径和叶周长。
实现方法:
首先,我们需要这样拍摄一张植物的图片,需要一个黑色的底板,一张A4纸,拍摄时需要将植物叶面放平,A4纸的四个直角都需要拍摄进照片中,确保A4纸与底下的黑色卡纸在照片边上有黑边(既是为了方便拍摄,也是为了方便计算):
然后我们的步骤是:
找出照片中的最大轮廓(此时理所当然是我们的A4纸)→进行图像的矫正透视变换将照片的黑边去掉
如何一步到位拿到真实值?
我们知道要想得到真实的叶面积、叶直径和叶周长,需要一些已知长度的东西来作为比例对照物,这里我选择用A4纸来作为现实比例对照物,通过
公式(1):测得植物像素值/植物真实值=测得A4纸像素值/A4真实值
这里面的“测得植物像素值”“测得A4纸像素值”和“A4真实值”我们都知道,那么就可以计算植物真实值。
如何得到植物的真实叶面积?
去黑边照片→找到最大轮廓(理所当然是植物轮廓)→得到轮廓的像素面积→公式(1)计算
如何得到植物的真实叶直径?
去黑边照片→找到最大轮廓(理所当然是植物轮廓)→对该轮廓画圆→得到圆的直径(直径即为植物叶直径)→公式(1)计算
如何得到植物的真实叶周长?
去黑边照片→找到最大轮廓(理所当然是植物轮廓)→得到该轮廓周长(该轮廓周长即为植物叶周长)→公式(1)计算
源码分享:
img1为带黑边的原始图像,warp_imgs为图像矫正透视变换后的去黑边图像,其余py文件分享在下面,计算周长的代码自行去获取轮廓周长套公式(1)进行计算:
get_area_final.py:
import cv2
import numpy as np
def sort_contours_size(cnts):
"""根据大小对轮廓进行排序"""
cnts_sizes = []
for contour in cnts:
cnt_size = cv2.contourArea(contour)
cnts_sizes.append([cnt_size,contour])
cnts_sizes.sort(key=lambda x:x[0], reverse=True)
return cnts_sizes
def get_area_main(path):
img = cv2.imread(path)
#变成单通道的黑白图片
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#二值化 返回阈值和二值化后图
thresh,binary = cv2.threshold(gray,150,255,cv2.THRESH_BINARY)
# cv2.imshow("img1",binary)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# 查找轮廓 返回轮廓和层级
contours, hierarchy = cv2.findContours(binary.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓会直接修改原图
img_copy = img.copy()
cv2.drawContours(img_copy, contours, -1, (0, 0, 255), 2)
# cv2.imshow('img_con', img_copy)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
contour_sizes = sort_contours_size(contours)
cnt = contour_sizes[1][1]
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
# print(center,radius)
cv2.circle(img_copy, center, radius, (255, 0, 0), 2)
# cv2.imshow('img_con2', img_copy)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
p_zhi = contour_sizes[0][0]
p_ye = contour_sizes[1][0]
# print(p_zhi,p_ye)
s_zhi = 623.7 # 纸29.7 21
s_ye = (p_ye * s_zhi) / p_zhi
zhi_chang_jia=img.shape[0]
zhi_changzheng=29.7
ye_long_zheng=(zhi_changzheng*2*radius)/zhi_chang_jia
return s_ye,ye_long_zheng
# path="warp_imgs/warp3.jpg"
# img = cv2.imread(path)
# print(img.shape[0])
get_warp_img_final.py:
import cv2
import numpy as np
minArea = 1000
filter = 4
scale = 2
wp = 210 * scale
hp = 297 * scale
def getContours(img):
imgG = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
imgBlur = cv2.GaussianBlur(imgG,(5,5),1)
imgCanny = cv2.Canny(imgBlur,100,100)
kernel = np.ones((5,5))
imgDial = cv2.dilate(imgCanny,kernel,iterations=3)
imgThre = cv2.erode(imgDial,kernel,iterations=2)
# cv2.imshow('res',imgCanny)
# cv2.imshow('res2',imgThre)
contours, hiearchy = cv2.findContours(imgThre,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
finalCountours = []
for i in contours:
area = cv2.contourArea(i)
if area> minArea:
# 计算轮廓的周长,true表示轮廓为封闭
peri = cv2.arcLength(i,True)
#进行轮廓的多边拟合
appprox = cv2.approxPolyDP(i,0.02*peri,True)
bbox = cv2.boundingRect(appprox)
if filter > 0 :
if(len(appprox))==filter:
finalCountours.append([len(appprox),area,appprox,bbox,i,peri])
else:
finalCountours.append([len(appprox), area, appprox, bbox, i,peri])
# 对第二个数值面积进行排序,为升序,找出轮廓的最大值
finalCountours = sorted(finalCountours, key=lambda x: x[1], reverse=True)
for con in finalCountours:
cv2.drawContours(img,con[4],-1, (0, 0, 255), 4)
return img,finalCountours
def reorder(myPoints):
#print(myPoints.shape)
myPointsNew = np.zeros_like(myPoints)
myPoints = myPoints.reshape((4,2))
add = myPoints.sum(1)
myPointsNew[0] = myPoints[np.argmin(add)]
myPointsNew[3] = myPoints[np.argmax(add)]
diff = np.diff(myPoints,axis=1)
myPointsNew[1]= myPoints[np.argmin(diff)]
myPointsNew[2] = myPoints[np.argmax(diff)]
# print(myPoints)
# print(myPoints)
return myPointsNew
def warpImg (img,points,w,h,pad=20):
# print(points)
points =reorder(points)
pts1 = np.float32(points)
pts2 = np.float32([[0,0],[w,0],[0,h],[w,h]])
matrix = cv2.getPerspectiveTransform(pts1,pts2)
imgWarp = cv2.warpPerspective(img,matrix,(w,h))
imgWarp = imgWarp[pad:imgWarp.shape[0]-pad,pad:imgWarp.shape[1]-pad]
return imgWarp
def get_warp_main(path):
img = cv2.imread(path)
img = cv2.resize(img, (0, 0), None, 0.5, 0.5)
imgcon, cons= getContours(img)
if(len(cons)!=0):
maxbox = cons[0][2]
new_maxbox = reorder(maxbox)
# cv2.imshow('img', imgcon)
imgWarp = warpImg(imgcon, new_maxbox, wp, hp)
# cv2.imshow('imgWarp',imgWarp)
name = path.split('/')[-1]
cv2.imwrite("./warp_imgs/warp{}".format(name), imgWarp)
main_final.py:
"""利用opencv读取并显示一个目录下的全部图片"""
import os
import cv2
from get_area_final import get_area_main
from get_warp_img_final import get_warp_main
path = './img1'
# 读取path文件夹下所有文件的名字
imagelist = os.listdir(path)
print(imagelist)
i = 0
for imgname in imagelist:
if (imgname.endswith(".jpg")):
full_path = path + '/' + imgname
get_warp_main(full_path)
name = imgname.split('.')[0]
print('name:',imgname,"完成")
i += 1
print(i)
path = './warp_imgs'
# 读取path文件夹下所有文件的名字
imagelist = os.listdir(path)
print(imagelist)
i = 0
for imgname in imagelist:
if (imgname.endswith(".jpg")):
full_path = path + '/' + imgname
get_area,get_long = get_area_main(full_path)
name = imgname.split('.')[0]
print('name:',imgname,"area:",get_area,"long:",get_long)
i += 1
print(i)
如果这篇文章能够帮助到你的话,还请点个赞赞呀!
Guff_hys_python数据结构,大数据开发学习,python实训项目-CSDN博客文章来源:https://www.toymoban.com/news/detail-766761.html
1 | 1 |
2 | 2 |
3 | 3 |
OpenCV是一个开源的计算机视觉和机器学习软件库。它由一系列用C++和Python编写的函数构成,可以在Windows、Linux和Mac操作系统上运行。OpenCV提供了一系列用于图像处理、计算机视觉、模式识别和机器学习的工具和算法,包括图像处理、特征检测、目标识别、运动跟踪、立体视觉和深度学习等功能。OpenCV的应用领域包括医学图像处理、人脸识别、行人检测、自动驾驶、机器人视觉和增强现实等。由于其功能强大和易用性,OpenCV已经成为计算机视觉和图像处理领域的重要工具之一。文章来源地址https://www.toymoban.com/news/detail-766761.html
到了这里,关于opencv计算植物叶面积_叶直径_叶周长_python的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!