opencv calculates plant leaf area_leaf diameter_leaf circumference_python

Project Description
Internship method
Source code sharing

Project Description:

Use the opencv library that comes with python to calculate the leaf area, leaf diameter and leaf circumference of plant leaves. You can directly get the real leaf area, leaf diameter and leaf circumference by taking pictures.

Implementation:

First of all, we need to take a picture of a plant like this. We need a black base plate and a piece of A4 paper. When taking the picture, we need to lay the plant leaves flat. The four right angles of the A4 paper need to be taken into the photo. Make sure that the A4 paper is in line with the picture. The black cardboard underneath has a black border on the edge of the photo (both for convenience of shooting and calculation):

Then our steps are:

Find the largest outline in the photo (of course it is our A4 paper at this time) → perform corrective perspective transformation of the image to remove the black edges of the photo

How to get the real value in one step?

We know that in order to get the real leaf area, leaf diameter and leaf circumference, we need something with a known length as a proportional control. Here I choose to use A4 paper as a realistic proportional control. By

Formula (1): Measured plant pixel value/true plant value = measured A4 paper pixel value/A4 true value

We all know the " measured plant pixel value ", " measured A4 paper pixel value " and " A4 real value ", then we can calculate the real value of the plant.

How to get the true leaf area of ​​a plant?

Remove black edges from the photo → find the largest contour (of course it is the plant contour) → get the pixel area of ​​the contour → calculate with formula (1)

How to get the true leaf diameter of a plant?

Remove the black edges from the photo → Find the largest outline (of course it is the outline of the plant) → Draw a circle on the outline → Get the diameter of the circle (the diameter is the diameter of the plant leaf) → Calculate with formula (1)

How to get the true leaf circumference of a plant?

Remove the black edges from the photo → find the largest outline (of course it is the outline of the plant) → get the perimeter of the outline (the perimeter of the outline is the circumference of the plant leaves) → calculate with formula (1)

Source code sharing:

img1 is the original image with black edges, warp_imgs is the image with black edges removed after image correction perspective transformation, and the rest of the py files are shared below. The code for calculating the perimeter is used to obtain the outline perimeter formula (1) for calculation:

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)

If this article can help you, please give it a like!

Guff_hys_python data structure, big data development learning, python training project-CSDN blog

1 1
2 2
3 3

OpenCV is an open source computer vision and machine learning software library. It consists of a series of functions written in C++ and Python and can run on Windows, Linux and Mac operating systems. OpenCV provides a series of tools and algorithms for image processing, computer vision, pattern recognition, and machine learning, including image processing, feature detection, target recognition, motion tracking, stereo vision, and deep learning. The application fields of OpenCV include medical image processing, face recognition, pedestrian detection, autonomous driving, robot vision and augmented reality, etc. Due to its power and ease of use, OpenCV has become one of the important tools in the field of computer vision and image processing.

Guess you like

Origin blog.csdn.net/HYSliuliuliu/article/details/133976781
Recommended