Detecting the onion co-ordinates in an onion field

Question:

Due to lack of data, I have been asked to implement a non-data driven approach to find the co-ordinates of the onions in the onion field. The image would be an elevated front view.

Here is the image of an Onion Field:

image

I have tried the following:

img = cv2.imread("/content/Onion1.jpeg",0)
img_blur = cv2.blur(img,(5,5))
edges = cv2.Canny(img_blur,150,200)

The final output obtained:

Output

What are the ways through which I can do better to achieve the objective i.e. to find out the co-ordinates of the onions in the image?
Can we somehow take the advantage that onions are planted in rows or some other obvious fact that I am clearly missing?
Any help/advice is highly appreciated. Also, note that I am very new to OpenCV.

Edit : I have been able to isolate the green but am struggling to perform multiple template matching in order to find the peaks or peak co-ordinates.

Here is the output I got by separating the hue corresponding to green:
Output

Code:

import cv2
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from google.colab.patches import cv2_imshow
## Read
img = cv2.imread("/content/Onion1.jpeg")
img = cv2.blur(img, (10,10))
cv2_imshow(img)


## convert to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

## mask of green (36,25,25) ~ (86, 255,255)
# mask = cv2.inRange(hsv, (36, 25, 25), (86, 255,255))
mask = cv2.inRange(hsv, (36, 25, 25), (86, 255,255))

## slice the green
imask = mask>0
green = np.zeros_like(img, np.uint8)
green[imask] = img[imask]

## show
cv2_imshow(green)

img_gray = cv2.cvtColor(green, cv2.COLOR_BGR2GRAY)
template = cv2.imread('/tp.png',0) # tp is just a screenshot taken of one of the peaks
w, h = template.shape[::-1]
res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
    cv2.rectangle(green, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)

cv2_imshow(green)

How can I generalise this peak detection so that it is a bit more robust?

Asked By: codeWITHswap

||

Answers:

This is a classification using k-means, which finds the onions, because they are clearly differentiated by his color, but this will not work with other photographs in general.

It separates the image in numClustersToIdentify = 4 different colors

from sklearn.cluster import KMeans
import numpy as np
import cv2
import matplotlib.pyplot as plt
import math


def downloadImage(URL):
    """Downloads the image on the URL, and convers to cv2 BGR format"""
    from io import BytesIO
    from PIL import Image as PIL_Image
    import requests

    response = requests.get(URL)
    image = PIL_Image.open(BytesIO(response.content))
    return cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB)


URL = "https://i.stack.imgur.com/eVS6X.jpg"

# Read image
im = downloadImage(URL)


# types of colors to be detected
numClustersToIdentify = 4

# classify the image in types of colors
linearImg = im.reshape((im.shape[1]*im.shape[0], 3))
kmeans = KMeans(n_clusters=numClustersToIdentify)
s = kmeans.fit(linearImg)
imgLabels = s.labels_.reshape(im.shape[0], im.shape[1]).astype(np.uint8)
imgLabels = cv2.normalize(imgLabels, None, 0, 255,
                          cv2.NORM_MINMAX, cv2.CV_8UC1)

cv2.imshow("Image", im)
cv2.waitKey(10)
cv2.imshow("Labels", imgLabels)
cv2.waitKey(10)

columns = 3
fig, ax = plt.subplots(
    math.ceil(numClustersToIdentify/columns), columns, squeeze=False)

for i, label in enumerate(np.unique(imgLabels)):
    ax[i//columns, i % columns].imshow(imgLabels == label)
    ax[i//columns, i % columns].axis('off')
plt.show()

enter image description here

Answered By: Colim

I have the feeling that detecting the green color can be a good starting point.

In the picture below, the Hue component has been used and clearly shows the distinction between the vegetation and the soil. The next step would be to find the peaks, which can be robustly achieved by grayscale correlation. (We used the second peak as the template and found the other three; the figures are matching scores.)

enter image description here]1

enter image description here

Now the onions could be more precisely located by some local search near the tip of the peaks.

Answered By: Yves Daoust