Spaces:
Build error
Build error
| """ | |
| CS5330 Fall 2024 | |
| Lab 2 Texture Classification | |
| Calvin Lo | |
| """ | |
| import gradio as gr | |
| import numpy as np | |
| import joblib | |
| from skimage.feature import local_binary_pattern, graycomatrix, graycoprops | |
| IMAGE_SIZE_GLCM = 256 | |
| IMAGE_SIZE_LBP = 128 | |
| RADIUS = 1 | |
| N_POINTS = 8 * RADIUS | |
| LBP_METHOD = "uniform" | |
| def get_feature_vector(img, feature_type): | |
| # convert to grayscale | |
| img_gray = img.convert("L") | |
| # resize and get feature vector | |
| if feature_type == "GLCM": | |
| img_resized = image_resize(img_gray, IMAGE_SIZE_GLCM) | |
| feature_vector = compute_glcm_histogram_pil(img_resized) | |
| else: | |
| img_resized = image_resize(img_gray, IMAGE_SIZE_LBP) | |
| feature_vector = get_lbp_hist(np.array(img_resized), | |
| N_POINTS, | |
| RADIUS, | |
| LBP_METHOD) | |
| return [feature_vector] | |
| def compute_glcm_histogram_pil(image, distances=[1], | |
| angles=[0], | |
| levels=8, | |
| symmetric=True): | |
| # Convert the PIL image to a NumPy array | |
| image_np = np.array(image) | |
| # Quantize the grayscale image to the specified number of levels | |
| image_np = (image_np * (levels - 1) / 255).astype(np.uint8) | |
| # Compute the GLCM using skimage's graycomatrix function | |
| glcm = graycomatrix(image_np, | |
| distances=distances, | |
| angles=angles, | |
| levels=levels, | |
| symmetric=symmetric, | |
| normed=True) | |
| # Extract GLCM properties | |
| homogeneity = graycoprops(glcm, 'homogeneity')[0, 0] | |
| correlation = graycoprops(glcm, 'correlation')[0, 0] | |
| # Create the feature vector | |
| feature_vector = np.array([homogeneity, correlation]) | |
| return feature_vector | |
| def get_lbp_hist(gray_image, n_points, radius, method): | |
| # Compute LBP for the image | |
| lbp = local_binary_pattern(gray_image, n_points, radius, method) | |
| lbp_hist, _ = np.histogram(lbp.ravel(), bins=np.arange(0, n_points + 3), | |
| range=(0, n_points + 2)) | |
| # Normalize the histogram | |
| lbp_hist = lbp_hist.astype("float") | |
| lbp_hist /= (lbp_hist.sum() + 1e-6) # Normalized histogram | |
| return lbp_hist | |
| def image_resize(img, n): | |
| # Crop the image to a square by finding the minimum dimension | |
| min_dimension = min(img.size) | |
| left = (img.width - min_dimension) / 2 | |
| top = (img.height - min_dimension) / 2 | |
| right = (img.width + min_dimension) / 2 | |
| bottom = (img.height + min_dimension) / 2 | |
| img = img.crop((left, top, right, bottom)) | |
| img = img.resize((n, n)) | |
| return img | |
| def classify(img, feature_type): | |
| # To load the model later | |
| loaded_model = joblib.load(feature_type + '_model.joblib') | |
| feature_vector = get_feature_vector(img, feature_type) | |
| # Make predictions with the loaded model | |
| label = loaded_model.predict(feature_vector) | |
| return f"{label[0]}" | |
| def main(): | |
| # Gradio interface | |
| with gr.Blocks() as interface: | |
| gr.Markdown("## Image Texture Classifier") | |
| # Image upload input | |
| img_input = gr.Image(type="pil") | |
| # Dropdown for selecting classifier | |
| classifier_dropdown = gr.Dropdown(choices=["GLCM", "LBP"], | |
| label="Feature Vector Type", | |
| value="GLCM") | |
| # Button for classification | |
| classify_button = gr.Button("Classify Image") | |
| # Output label | |
| output_label = gr.Textbox(label="Predicted Texture") | |
| # Set up interaction | |
| classify_button.click(fn=classify, | |
| inputs=[img_input, classifier_dropdown], | |
| outputs=output_label) | |
| # Launch the interface | |
| interface.launch() | |
| if __name__ == "__main__": | |
| main() | |