Rachit Anand
Rachit Anand

Reputation: 55

How can I extract only the middle bone in this image using only erosion, dilation, and, xor and thresholding?

I am using opencv to extract the middle big bone from this image and I can't seem to workout how to do itInput Image

Where I am right now

As you see, all 3 bones are showing but I only want the middle bone Here is the code

b =  cv.imread('content/B.tif', cv.IMREAD_GRAYSCALE)

plt.figure(figsize=(5,5))
plt.imshow(b, cmap='gray')
plt.axis('off')
plt.show()

_, binary_b = cv.threshold(b, 200, 255, cv.THRESH_BINARY)
b_e = cv.erode(binary_b, np.ones((1,1), dtype=np.uint8))
b_d = cv.dilate(b_e, np.ones((5,5), dtype=np.uint8),iterations = 3)

xor = cv.bitwise_and(b_d,b)

plt.figure(figsize=(5,5))
plt.imshow(xor, cmap='gray')
plt.axis('off')
plt.show()

Can someone help please?

Upvotes: 0

Views: 69

Answers (1)

KRG
KRG

Reputation: 956

I tried to find the center bone as it's largest using contour. Please see code below with explanation in comments. Hope this helps.

import cv2
import numpy as np

#Read image and convert to gray scale
image = cv2.imread("bone.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresholded_image = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)

#Dilate image to close gaps
#Erode image to remove additional edges created using dilation
#number of iteration found by trial and error
kernel = np.ones((5,5),np.uint8)
thresholded_image = cv2.dilate(thresholded_image, kernel,iterations=5)
thresholded_image = cv2.erode(thresholded_image, kernel,iterations=5)

#get the contour of dilate eroded image
contours, hierarchy = cv2.findContours(thresholded_image, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

#Since center bone is largest
#Find contour with max length
max_length=0
max_length_ctr=None
for ctr in contours:
    x,y,w,h = cv2.boundingRect(ctr)
    if h > max_length:
        max_length = h
        max_length_ctr = ctr

#Use the found contour to create mask and get the bone
if max_length_ctr is not None:
    big_bone_mask = np.zeros_like(thresholded_image)
    cv2.drawContours(big_bone_mask, [max_length_ctr], -1, (255, 255, 255), -1)
    cv2.imwrite("big_bone_mask.png",big_bone_mask)

    # Get the graph from original image from the mask
    bone_image = cv2.bitwise_and(image, image, mask=big_bone_mask)
    cv2.imwrite("bone_image.png", bone_image)

Output enter image description here

Upvotes: 0

Related Questions