3

bee veins

I need to detect the vein junctions of wings bee (the image is just one example). I use opencv - python.

ps: maybe the image lost a little bit of quality, but the image is all connected with one pixel wide.

Vasu Deo.S
  • 1,820
  • 1
  • 11
  • 23
João
  • 175
  • 1
  • 2
  • 10

2 Answers2

3

This is an interesting question. The result I got is not perfect, but it might be a good start. I filtered the image with a kernel that only looks at the edges of the kernel. The idea being, that a junction has at least 3 lines that cross the kernel-edge, where regular lines only have 2. This means that when the kernel is over a junction, the resulting value will be higher, so a threshold will reveal them.
Due to the nature of the lines there are some value positives and some false negatives. A single joint will most likely be found several times, so you'll have to account for that. You can make them unique by drawing small dots and detecting those dots.

Result:

enter image description here

Code:

    import cv2
    import numpy as np
    # load the image as grayscale
    img = cv2.imread('xqXid.png',0)
    # make a copy to display result
    im_or = img.copy()
    # convert image to larger datatyoe
    img.astype(np.int32)
    # create kernel 
    kernel = np.ones((7,7))
    kernel[2:5,2:5] = 0
    print(kernel)
    #apply kernel
    res = cv2.filter2D(img,3,kernel)
    # filter results
    loc = np.where(res > 2800)
    print(len(loc[0]))
    #draw circles on found locations
    for x in range(len(loc[0])):
            cv2.circle(im_or,(loc[1][x],loc[0][x]),10,(127),5)
    #display result
    cv2.imshow('Result',im_or)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

Note: you can try to tweak the kernel and the threshold. For example, with the code above I got 126 matches. But when I use

kernel = np.ones((5,5))
kernel[1:4,1:4] = 0

with threshold

loc = np.where(res > 1550)

I got 33 matches in these locations:

enter image description here

J.D.
  • 4,511
  • 2
  • 7
  • 20
  • Check also my code here: https://stackoverflow.com/questions/22058485/how-to-implement-an-function-equivalent-to-bwmorph-matlab-function-in-opencv/22060992#22060992 – Andrey Smorodov Jul 21 '19 at 14:51
2

You can use Harris corner detector algorithm to detect vein junction in above image. Compared to the previous techniques, Harris corner detector takes the differential of the corner score into account with reference to direction directly, instead of using shifting patches for every 45 degree angles, and has been proved to be more accurate in distinguishing between edges and corners (Source: wikipedia).

code:

img = cv2.imread('wings-bee.png')
# convert image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)

'''
args:
img - Input image, it should be grayscale and float32 type.
blockSize - It is the size of neighbourhood considered for corner detection
ksize - Aperture parameter of Sobel derivative used.
k - Harris detector free parameter in the equation.
'''
dst = cv2.cornerHarris(gray, 9, 5, 0.04)
# result is dilated for marking the corners
dst = cv2.dilate(dst,None)

# Threshold for an optimal value, it may vary depending on the image.
img_thresh = cv2.threshold(dst, 0.32*dst.max(), 255, 0)[1]
img_thresh = np.uint8(img_thresh)

# get the matrix with the x and y locations of each centroid
centroids = cv2.connectedComponentsWithStats(img_thresh)[3]


stop_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# refine corner coordinates to subpixel accuracy
corners = cv2.cornerSubPix(gray, np.float32(centroids), (5,5), (-1,-1), stop_criteria)
for i in range(1, len(corners)):
    #print(corners[i])
    cv2.circle(img, (int(corners[i,0]), int(corners[i,1])), 5, (0,255,0), 2)

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

output:

enter image description here

You can check the theory behind Harris Corner detector algorithm from here.

Anubhav Singh
  • 8,321
  • 4
  • 25
  • 43