简体   繁体   English

如何检测二进制图像中的某种形状(植物茎)?

[英]how can I detect a certain shape (plant stem) in a binary image?

I'm working on a shape based leaf classification project when i got stuck for hours trying to figure out how to rotate the image based on the stem of the leaf.当我被困了几个小时试图弄清楚如何根据叶子的茎旋转图像时,我正在研究一个基于形状的叶子分类项目。

Here is an example of an input image.这是输入图像的示例。

sample样本

I have been trying to apply morphological transformations with opencv and filter2D with different kernels and even HoughLines, this is the closes I have gotten so far.我一直在尝试使用 opencv 和 filter2D 使用不同的内核甚至 HoughLines 应用形态学变换,这是我迄今为止得到的结果。

detected-steam检测到的蒸汽

Any help would be appreciated, thanks in advance.任何帮助将不胜感激,在此先感谢。


EDIT编辑

The position of the stem is important because of the different kind of leaves I'm trying to classify, so What I'm trying to acomplish is to get the leaf in a vertical position with the stem being at the bottom.茎的 position 很重要,因为我要分类的叶子种类不同,所以我要完成的是将叶子放在垂直的 position 中,茎在底部。

The images I provided are the thresholded images, I leave the original one down here.我提供的图像是阈值图像,我将原始图像留在这里。

在此处输入图像描述

I provide a second sample because I in this particular case i couldn't get the stem at the bottom so it ended up being at the top.我提供了第二个样本,因为在这种特殊情况下,我无法将茎放在底部,所以它最终位于顶部。

在此处输入图像描述

Sample returning 2 degrees.样品返回 2 度。

在此处输入图像描述

Here is one idea.这是一个想法。 Fit an ellipse to thresholded leaf shape (assuming it will be longer than wide).将椭圆拟合到阈值叶形(假设它长于宽)。

Input:输入:

在此处输入图像描述

import cv2
import numpy as np

# read image
img = cv2.imread('leaf.png')

# threshold on color
lower=(84,1,68)
upper=(84,1,68)
thresh = cv2.inRange(img, lower, upper)

# get contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# fit ellipse to leaf contours
ellipse = cv2.fitEllipse(big_contour)
(xc,yc), (d1,d2), angle = ellipse
print(xc,yc,d1,d1,angle)

# draw ellipse on copy of input
result = img.copy() 
cv2.ellipse(result, ellipse, (0,0,255), 1)

# save results
cv2.imwrite('leaf_threshold.png',thresh)
cv2.imwrite('leaf_ellipse.png',result)

# show results
cv2.imshow("thresh", thresh)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Threshold image:阈值图像:

在此处输入图像描述

Ellipse image:椭圆图像:

在此处输入图像描述 \ \

Ellipse Information:椭圆信息:

126.44944763183594 101.98369598388672 112.40930938720703 112.40930938720703 89.33087158203125

So angle = 89.33087158203125 deg (cw from -y axis, i.e. from the top) or 
   angle = 0.66912841796875 deg (ccw from the x axis, i.e. from right side)

ADDITION:添加:

Here is a more complete solution.这是一个更完整的解决方案。 But it assumes the leaf will be longer than wide so that the ellipse major axis aligns along the step direction.但它假设叶子长于宽,因此椭圆长轴沿步进方向对齐。

Leaf 1:叶1:

在此处输入图像描述

Leaf 2:叶 2:

在此处输入图像描述

import cv2
import numpy as np

# read image
#img = cv2.imread('leaf1.jpg')
img = cv2.imread('leaf2.jpg')

# threshold on color
lower=(0,0,0)
upper=(130,190,140)
thresh = cv2.inRange(img, lower, upper)

# get contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# fit ellipse to leaf contours
ellipse = cv2.fitEllipse(big_contour)
(xc,yc), (d1,d2), angle = ellipse
print(xc,yc,d1,d1,angle)

# draw ellipse on copy of input
graphic = img.copy() 
cv2.ellipse(graphic, ellipse, (0,0,255), 1)


# rotate image so step points downward   
if angle >= 135 and angle <=180:
    result = cv2.rotate(img, cv2.ROTATE_180)
elif angle >= 45 and angle <135:
    result = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
elif angle >= 0 and angle <45:
    result = img.copy()
    

# save results
cv2.imwrite('leaf2_threshold.png',thresh)
cv2.imwrite('leaf2_ellipse.png',graphic)
cv2.imwrite('leaf2_result.png',result)

# show results
cv2.imshow("thresh", thresh)
cv2.imshow("graphic", graphic)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Leaf 1 Threshold:叶 1 阈值:

在此处输入图像描述

Leaf 1 Ellipse:叶 1 椭圆:

在此处输入图像描述

Leaf 1 Rotated:叶 1 旋转:

在此处输入图像描述

Leaf 2 Threshold:叶 2 阈值:

在此处输入图像描述

Leaf 2 Ellipse:叶 2 椭圆:

在此处输入图像描述

Leaf 2 Rotated:叶 2 旋转:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM