Spaces:
Runtime error
Runtime error
import cv2 | |
import numpy as np | |
import gradio as gr | |
def pirahansiah_threshold_method_find_threshold_values_2(grayImg): | |
#http://www.jatit.org/volumes/Vol95No21/1Vol95No21.pdf | |
#https://pdfs.semanticscholar.org/05b2/d39fce4e8a99897e95f8c75416f65a5a0acc.pdf | |
assert grayImg is not None, "file could not be read, check with os.path.exists()" | |
#img = cv2.GaussianBlur(self.grayImg, (3, 3), 0) | |
img = grayImg | |
# Initialize an array to store the PSNR values for each threshold value | |
psnr_values = np.zeros(256) | |
psnr_max=0 | |
th=0 | |
# Iterate over all possible threshold values with a step size of 5 | |
for t in range(0, 256, 5): | |
# Threshold the image using the current threshold value | |
_, binary = cv2.threshold(img, t, 255, cv2.THRESH_BINARY) | |
# Calculate the PSNR between the binary image and the original image | |
psnr = cv2.PSNR(binary, img) | |
# Store the PSNR value | |
psnr_values[t] = psnr | |
if (psnr_max<psnr): | |
psnr_max=psnr | |
th=t | |
# Calculate the mean PSNR value | |
mean_psnr = np.mean(psnr_values) | |
th=int(th/mean_psnr) | |
# Find the threshold values that satisfy the condition | |
thresh = th #np.argwhere((mean_psnr / k1 < psnr_values) & (psnr_values < mean_psnr / k2)).flatten() | |
return thresh | |
def pirahansiah_threshold_method_find_threshold_values_1(grayImg): | |
#https://www.jatit.org/volumes/Vol57No2/4Vol57No2.pdf | |
assert grayImg is not None, "file could not be read, check with os.path.exists()" | |
gray = cv2.GaussianBlur(grayImg, (3, 3), 0) | |
max1=0 | |
max2=0 | |
# Iterate over all possible threshold values | |
for t in range(0, 256, 10): | |
# Threshold the image using the current threshold value | |
_, binary = cv2.threshold(gray, t, 255, cv2.THRESH_BINARY) | |
# Find the contours in the binary image | |
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
if max1<=len(contours): | |
max1=len(contours) | |
max2=t | |
threshold_values =max2 | |
return threshold_values | |
path = [['image_0.png']] | |
inputs_thresh = [ | |
gr.inputs.Image(type="filepath", label="Input Image"), | |
gr.components.Slider(label="Manual Threshold Value", value=125, minimum=10, maximum=255, step=5), | |
gr.inputs.Radio(label="Threshold Methods", | |
choices=[ | |
"cv2.threshold(grayImg, 128, 255, cv2.THRESH_BINARY)" | |
,"cv2.threshold(grayImg, 128, 255, cv2.THRESH_BINARY_INV)" | |
,"cv2.threshold(grayImg, 128, 255, cv2.THRESH_TRUNC)" | |
,"cv2.threshold(grayImg, 128, 255, cv2.THRESH_TOZERO)" | |
,"cv2.threshold(grayImg, 128, 255, cv2.THRESH_TOZERO_INV)" | |
,"cv2.adaptiveThreshold(grayImg, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)" | |
,"cv2.threshold(grayImg, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU,)" | |
,"Adapted from PirahanSiah Threshold Method I derivative demo" | |
,"Inspired by PirahanSiah Threshold Method II derivative demo" | |
]), | |
] | |
outputs_thresh = [ | |
gr.outputs.Image(type="numpy", label="Output Image") | |
] | |
def process_image(input_image, slider_val, radio_choice): | |
img = cv2.imread(input_image,0) | |
_, binaryImg = cv2.threshold(img, slider_val, 255, cv2.THRESH_BINARY) | |
if radio_choice == "cv2.threshold(grayImg, 128, 255, cv2.THRESH_BINARY)": | |
_, binaryImg=cv2.threshold(img, 128, 255, cv2.THRESH_BINARY) | |
elif radio_choice == "cv2.threshold(grayImg, 128, 255, cv2.THRESH_BINARY_INV)": | |
_, binaryImg=cv2.threshold(img, 128, 255, cv2.THRESH_BINARY_INV) | |
elif radio_choice == "cv2.threshold(grayImg, 128, 255, cv2.THRESH_TRUNC)": | |
_, binaryImg=cv2.threshold(img, 128, 255, cv2.THRESH_TRUNC) | |
elif radio_choice == "cv2.threshold(grayImg, 128, 255, cv2.THRESH_TOZERO)": | |
_, binaryImg=cv2.threshold(img, 128, 255, cv2.THRESH_TOZERO) | |
elif radio_choice == "cv2.threshold(grayImg, 128, 255, cv2.THRESH_TOZERO_INV)": | |
_, binaryImg=cv2.threshold(img, 128, 255, cv2.THRESH_TOZERO_INV) | |
elif radio_choice == "cv2.adaptiveThreshold(grayImg, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)": | |
binaryImg=cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) | |
elif radio_choice == "cv2.threshold(grayImg, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU,)": | |
_, binaryImg=cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU,) | |
elif radio_choice == "Adapted from PirahanSiah Threshold Method I derivative demo": | |
threshval=pirahansiah_threshold_method_find_threshold_values_1(img) | |
_, binaryImg = cv2.threshold(img, threshval, 255, cv2.THRESH_BINARY) | |
elif radio_choice == "Inspired by PirahanSiah Threshold Method II derivative demo": | |
threshval=pirahansiah_threshold_method_find_threshold_values_2(img) | |
_, binaryImg = cv2.threshold(img, threshval, 255, cv2.THRESH_BINARY) | |
return binaryImg | |
def on_change(slider_val, radio_choice): | |
# Update output | |
outputs_thresh[0].update(process_image( | |
inputs_thresh[0].value, | |
slider_val, | |
radio_choice) | |
) | |
threshold_methods = gr.Interface( | |
fn=process_image, | |
inputs=inputs_thresh, | |
outputs=outputs_thresh, | |
on_change=on_change, | |
examples=path, | |
title="Computer Vision and Deep Learning by Farshid PirahanSiah", | |
live=True | |
) | |
# class Thresholding: | |
# def __init__(self, grayImg): | |
# self.grayImg = grayImg | |
# def manually_python(self): | |
# threshval = 128 | |
# binaryImg = np.where(self.grayImg < threshval, self.grayImg, 0) if threshval < 128 else np.where(self.grayImg > threshval, self.grayImg, 0) | |
# return binaryImg | |
# def manually(self,threshval): | |
# binaryImg = np.zeros_like(self.grayImg) | |
# for i in range(self.grayImg.shape[0]): #height | |
# for j in range(self.grayImg.shape[1]): #width | |
# if self.grayImg[i, j] < threshval: | |
# binaryImg[i, j] = 0 | |
# else: | |
# binaryImg[i, j] = 1 | |
# return binaryImg | |
# def pirahansiah_threshold_method_find_threshold_values_2(self): | |
# #http://www.jatit.org/volumes/Vol95No21/1Vol95No21.pdf | |
# #https://pdfs.semanticscholar.org/05b2/d39fce4e8a99897e95f8c75416f65a5a0acc.pdf | |
# assert self.grayImg is not None, "file could not be read, check with os.path.exists()" | |
# #img = cv2.GaussianBlur(self.grayImg, (3, 3), 0) | |
# img = self.grayImg | |
# # Initialize an array to store the PSNR values for each threshold value | |
# psnr_values = np.zeros(256) | |
# psnr_max=0 | |
# th=0 | |
# # Iterate over all possible threshold values with a step size of 5 | |
# for t in range(0, 256, 5): | |
# # Threshold the image using the current threshold value | |
# _, binary = cv2.threshold(img, t, 255, cv2.THRESH_BINARY) | |
# # Calculate the PSNR between the binary image and the original image | |
# psnr = cv2.PSNR(binary, img) | |
# # Store the PSNR value | |
# psnr_values[t] = psnr | |
# if (psnr_max<psnr): | |
# psnr_max=psnr | |
# th=t | |
# # Calculate the mean PSNR value | |
# mean_psnr = np.mean(psnr_values) | |
# th=int(th/mean_psnr) | |
# # Find the threshold values that satisfy the condition | |
# thresh = th #np.argwhere((mean_psnr / k1 < psnr_values) & (psnr_values < mean_psnr / k2)).flatten() | |
# return thresh | |
# def pirahansiah_threshold_method_find_threshold_values_1(self): | |
# #https://www.jatit.org/volumes/Vol57No2/4Vol57No2.pdf | |
# assert self.grayImg is not None, "file could not be read, check with os.path.exists()" | |
# gray = cv2.GaussianBlur(self.grayImg, (3, 3), 0) | |
# max1=0 | |
# max2=0 | |
# # Iterate over all possible threshold values | |
# for t in range(0, 256, 10): | |
# # Threshold the image using the current threshold value | |
# _, binary = cv2.threshold(gray, t, 255, cv2.THRESH_BINARY) | |
# # Find the contours in the binary image | |
# contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
# if max1<=len(contours): | |
# max1=len(contours) | |
# max2=t | |
# threshold_values =max2 | |
# return threshold_values | |
# def opencv_th(self): | |
# font = cv2.FONT_HERSHEY_SIMPLEX | |
# fontScale = 2 | |
# color = (0, 0, 0) | |
# colorInv = (255, 255, 255) | |
# thickness = 2 | |
# # Set the position of the text | |
# textX = 25 | |
# textY = 45 | |
# textSize, _ = cv2.getTextSize("Otsu Method ", font, fontScale, thickness) | |
# # Draw a white rectangle behind the text | |
# # Apply different thresholding methods | |
# _, binaryImg = cv2.threshold(self.grayImg, 128, 255, cv2.THRESH_BINARY) | |
# cv2.rectangle(binaryImg, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(binaryImg, 'Binary', (textX, textY), font, fontScale, color, thickness) | |
# _, binaryInvImg = cv2.threshold(self.grayImg, 128, 255, cv2.THRESH_BINARY_INV) | |
# cv2.rectangle(binaryInvImg, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(binaryInvImg, 'Binary Inv', (textX, textY), font, fontScale, color, thickness) | |
# _, truncImg = cv2.threshold(self.grayImg, 128, 255, cv2.THRESH_TRUNC) | |
# cv2.rectangle(truncImg, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(truncImg, 'Trunc', (textX, textY), font, fontScale, color, thickness) | |
# _, toZeroImg = cv2.threshold(self.grayImg, 128, 255, cv2.THRESH_TOZERO) | |
# cv2.rectangle(toZeroImg, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(toZeroImg, 'To Zero', (textX, textY), font, fontScale, color, thickness) | |
# _, toZeroInvImg = cv2.threshold(self.grayImg, 128, 255, cv2.THRESH_TOZERO_INV) | |
# cv2.rectangle(toZeroInvImg, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(toZeroInvImg, 'To Zero Inv', (textX, textY), font, fontScale, color, thickness) | |
# adaptiveImg = cv2.adaptiveThreshold(self.grayImg, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) | |
# cv2.rectangle(adaptiveImg, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(adaptiveImg, 'Adaptive', (textX, textY), font, fontScale, color, thickness) | |
# otsu_threshold, image_result = cv2.threshold(self.grayImg, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU,) | |
# cv2.rectangle(image_result, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(image_result, 'Otsu Threshold Method', (textX, textY), font, fontScale, color, thickness) | |
# threshval=self.pirahansiah_threshold_method_find_threshold_values_1() | |
# th_img = th.manually(threshval) | |
# binaryImg = th_img * 255 | |
# cv2.rectangle(binaryImg, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(binaryImg, 'PirahanSiah Threshold ', (textX, textY), font, fontScale, color, thickness) | |
# cv2.rectangle(self.grayImg, (textX, textY - textSize[1]), (textX + textSize[0], textY), (255, 255, 255), -1) | |
# cv2.putText(self.grayImg, 'Original', (textX, textY), font, fontScale, color, thickness) | |
# # Concatenate the images into a grid with 3 rows and 3 columns | |
# row1 = np.concatenate((self.grayImg, binaryImg, binaryInvImg), axis=1) | |
# row2 = np.concatenate((truncImg, toZeroImg, toZeroInvImg), axis=1) | |
# row3 = np.concatenate((adaptiveImg, image_result, binaryImg), axis=1) # np.zeros_like(adaptiveImg) | |
# concatenatedImg = np.concatenate((row1, row2, row3), axis=0) | |
# # Resize the concatenated image to fit the screen resolution | |
# screenRes = (1920-200, 1080-200) | |
# scaleWidth = screenRes[0] / concatenatedImg.shape[1] | |
# scaleHeight = screenRes[1] / concatenatedImg.shape[0] | |
# scale = min(scaleWidth, scaleHeight) | |
# windowWidth = int(concatenatedImg.shape[1] * scale) | |
# windowHeight = int(concatenatedImg.shape[0] * scale) | |
# resizedImg = cv2.resize(concatenatedImg, (windowWidth, windowHeight)) | |
# # Display the resized image | |
# cv2.imshow('Thresholded Images', resizedImg) | |
# cv2.waitKey(0) | |
# cv2.destroyAllWindows() | |
# if __name__ == "__main__": | |
# img = cv2.imread("opencv.png") | |
# gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
# th = Thresholding(gray) | |
# th.opencv_th() | |
#threshval = 128 | |
# read an image | |
# convert it to grayscale | |
#threshval=th.pirahansiah_threshold_method_find_threshold_values_1() | |
# threshval=th.pirahansiah_threshold_method_find_threshold_values_2() | |
# th_img = th.manually(threshval) | |
# binaryImg = th_img * 255 | |
# cv2.imshow('image', binaryImg) | |
# cv2.waitKey(100) | |
''' | |
cv::Mat binaryImg = threshval < 128 ? (grayImg < threshval) : (grayImg > threshval); | |
#thresholding #opencv #python | |
The PirahanSiah’s method for thresholding, described in the paper, uses a gray-scale histogram, | |
thresholding range, and the Peak Signal-to-Noise Ratio (PSNR) to segment images and find the best | |
threshold values to binarize the image. They argue that thresholding is an important problem in | |
pattern recognition and use the PSNR quality measure to assess the similarities between the | |
original and binarized image. They calculate PSNRs for every threshold value and use the | |
difference between the PSNR of the previous threshold image and the new one to select the | |
threshold value. They also describe a multi-threshold algorithm that applies multiple | |
threshold values and computes the total number of blobs or objects in an image for each threshold. | |
The peak threshold values are those with the highest total number of blobs compared to their threshold neighbors. | |
In addition, their method uses thresholding on images suitable for OCR systems, LPR systems, etc. | |
The proposed adaptive threshold method, based on the Peak Signal-to-Noise Ratio (PSNR), | |
has the potential to be applied in all domains, such as LPR and OCR. The proposed algorithm | |
achieves competitive results in four databases, including Malaysian vehicle, standard, | |
printed and handwritten images. The objective of this research was to develop a new single | |
adaptive thresholding algorithm that works for a wide range of pattern recognition applications. | |
The proposed method has been implemented in four different types of applications and compared | |
with other methods. The results show that the proposed algorithm achieves the objective because | |
it has obtained reasonable results in all four areas/domains. | |
https://www.jatit.org/volumes/Vol57No2/4Vol57No2.pdf | |
http://www.jatit.org/volumes/Vol95No21/1Vol95No21.pdf | |
https://pdfs.semanticscholar.org/05b2/d39fce4e8a99897e95f8c75416f65a5a0acc.pdf | |
''' |