Search code examples
pythonopencvimage-processing

How to detect object (Blood) from a picture in OpenCV python


I want to detect only object from a picture

now i can't detect the difference between BG and Object

original img, bg img:

1m 2m

import cv2
import numpy as np
import os

def detect_blood(input_path):

    img = cv2.imread(input_path)
    imgBlurred = cv2.GaussianBlur(img, (5,5), 0)
    gray = cv2.cvtColor(imgBlurred, cv2.COLOR_BGR2GRAY)

    ret2, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    kernel = np.ones((5, 5), np.uint8)
    mask = cv2.erode(thresh, kernel, iterations=2)
    mask = cv2.dilate(mask, kernel, iterations=2)
    foreground = cv2.bitwise_and(img, img, mask=mask)

    # Find contours in the mask
    min_area = 1000  # Adjust this value as needed
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    large_contours = [c for c in contours if cv2.contourArea(c) > min_area]
    
    # Draw the contours on the original image
    cv2.drawContours(foreground, large_contours, -1, (0, 255, 0), 3)

    # Resize the image to a smaller size
    resized_img = cv2.resize(img, (480, 640))# Resize the image to a smaller size
    resized_mask = cv2.resize(mask, (480, 640))
    resized_foreground = cv2.resize(foreground, (480, 640))

    # cv2.imshow("Original", resized_img)
    cv2.imshow("mask", resized_mask)
    cv2.imshow("output", resized_foreground)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    return foreground

def process_images(input_folder, output_folder):
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    for filename in os.listdir(input_folder):
        if filename.endswith(('.jpg', '.jpeg', '.png')):
            input_path = os.path.join(input_folder, filename) # "./Blood/blood(1).jpg"
            output_path = os.path.join(output_folder, 'result_{}'.format(filename)) # ./img_detect/result_

            result = detect_blood(input_path)
            cv2.imwrite(output_path, result)

if __name__ == "__main__":
    input_folder = "./BloodV2"
    output_folder = "./img_detect"

    process_images(input_folder, output_folder)

Mask and Result:

3m 4m


Solution

  • I tried to get the blood by filtering using red color and remove noises by contour area. Below if the code I used with explanations in comment. Hope this help

    import cv2
    import numpy as np
    
    image = cv2.imread('bld.jpg') #Read input image
    result = image.copy()
    
    #Convert to HSV and filter image using red as blood will be red
    image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    lower = np.array([155,25,0])
    upper = np.array([179,255,255])
    mask = cv2.inRange(image, lower, upper)
    mask = cv2.erode(mask, None, iterations=2)  # Erode to remove noise
    mask = cv2.dilate(mask, None, iterations=2)  # dilate to close gaps
    #Find contour
    contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # get contour
    
    #Remove small contours to avoid noises
    selected_contours = []
    for ct in contours:
        if cv2.contourArea(ct) > 10000:  # Select contours greater than a particular area value.
            selected_contours.append(ct)
    contour_image = np.zeros_like(mask)
    
    #Get the mask by drawing selected contour
    cv2.drawContours(contour_image, selected_contours, -1, (255), thickness=cv2.FILLED)
    result = cv2.bitwise_and(result, result, mask=contour_image)
    #Draw blood only image.
    cv2.imwrite("bld_out.jpg",result)
    

    Output Image : enter image description here