How to Apply threshold operator to highlight the largest object

167 Views Asked by At

I want to know how to apply threshold operator to highlight the largest object, which is the 3rd column of my output.

Using this code I am going to compare 3 images using np.hstack(). img_hubble is the original image, dst is the blurred image.

import cv2
import numpy as np
import matplotlib.pyplot as plt

# get image
img_hubble = cv2.imread("hubble.png", 0)

# define the kernel size
kernel = np.ones((15,15), np.float32)/225
dst = cv2.filter2D(img_hubble, -1, kernel)

#applying threshhold operator  to highlight the largest object
thresh = cv2.threshold(dst, 0, 255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

result = np.hstack((img_hubble,dst,thresh))
cv2.imshow('result',thresh )

cv2.waitKey()
cv2.destroyAllWindows()

Output of the image below.

Output

Above code give me the following error:

OpenCV(4.7.0) :-1: error: (-5:Bad argument) in function 'imshow'
> Overload resolution failed:
>  - mat is not a numerical tuple
>  - Expected Ptr<cv::cuda::GpuMat> for argument 'mat'
>  - Expected Ptr<cv::UMat> for argument 'mat'
1

There are 1 best solutions below

0
Oli_WH On

I've cleaned up the script and tried to solve what I believe your problem is.

Threshold returns 2 parameters, the threshold set, and the actual binary image:

_, thresh = cv2.threshold(dst, 0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

Grabs the binary image while ignoring the threshold value.

Thresholding is only going to return a binary image where groups of bright pixels are kept. It will not return a single largest group of bright pixels.

Connected component or Labelling needs to be used for that. here is a solution:

# labels the threshold image and get stats.
n_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh)

# get areas from stats
areas = stats[:,-1]

# find the second largest area (Assuming the largest is always the background)
index_largest_component = np.argsort(areas)[-2]
cv2.imshow('result',(labels==index_largest_component).astype(np.float32))

This will filter your threshold image to only show the largest group of bright pixels.

All together the code is as follows:

import cv2
import numpy as np

# get image
img_hubble = cv2.imread("hubble.jpg", cv2.IMREAD_GRAYSCALE)

# define the kernel size
kernel = np.ones((15,15), np.float32)/225
dst = cv2.filter2D(img_hubble, -1, kernel)

# applying threshhold operator  to highlight the largest object
_, thresh = cv2.threshold(dst, 0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# stack resulting images
result = np.hstack((img_hubble,dst,thresh))

# labels the threshold image and get stats.
n_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh)

# get areas from stats
areas = stats[:,-1]

# find the second largest area (Assuming the largest is always the background)
index_largest_component = np.argsort(areas)[-2]

# show stack and largest area
cv2.imshow('res',result)
cv2.imshow('result',(labels==index_largest_component).astype(np.float32))

cv2.waitKey()
cv2.destroyAllWindows()