File size: 3,157 Bytes
4bb934b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import numpy as np
import cv2
import matplotlib.pyplot as plt
from PIL import Image
import io

def otsu_threshold(image):
    hist, bin_edges = np.histogram(image.flatten(), bins=256, range=[0, 256])
    hist = hist.astype(float)
    total_pixels = image.size
    pixel_probability = hist / total_pixels

    max_variance = 0
    optimal_threshold = 0

    for threshold in range(1, 256):
        weight_background = np.sum(pixel_probability[:threshold])
        weight_foreground = np.sum(pixel_probability[threshold:])

        if weight_background == 0 or weight_foreground == 0:
            continue

        mean_background = np.sum(np.arange(threshold) * pixel_probability[:threshold]) / weight_background
        mean_foreground = np.sum(np.arange(threshold, 256) * pixel_probability[threshold:]) / weight_foreground

        variance = weight_background * weight_foreground * (mean_background - mean_foreground) ** 2

        if variance > max_variance:
            max_variance = variance
            optimal_threshold = threshold

    segmented_image = np.zeros_like(image)
    segmented_image[image >= optimal_threshold] = 255

    return optimal_threshold, segmented_image

def generate_segmented_image(image_path):
    # Convert PIL to OpenCV format
    print(f"Image path: {image_path}")
    image = Image.open(image_path)
    image_np = np.array(image)
    original_image = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)

    if len(original_image.shape) == 3:
        gray_image = cv2.cvtColor(original_image, cv2.COLOR_BGR2GRAY)
    else:
        gray_image = original_image.copy()

    blurred = cv2.GaussianBlur(gray_image, (5, 5), 0)

    # Our implementation
    our_threshold, our_segmented = otsu_threshold(blurred)

    # OpenCV's implementation
    opencv_threshold, opencv_segmented = cv2.threshold(
        blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU
    )

    # Create histogram figure
    fig, ax = plt.subplots(figsize=(6, 4))
    ax.hist(gray_image.ravel(), 256, [0, 256], color='gray')
    ax.axvline(x=our_threshold, color='red', linestyle='--', label=f'Ours: {our_threshold}')
    ax.axvline(x=opencv_threshold, color='green', linestyle='--', label=f'OpenCV: {opencv_threshold}')
    ax.set_title("Histogram with Thresholds")
    ax.legend()

    # Convert Matplotlib figure to image
    buf = io.BytesIO()
    plt.savefig(buf, format='png')
    buf.seek(0)
    hist_image = Image.open(buf)
    plt.close(fig)  # Close the figure to free memory


    return (
        image, 
        Image.fromarray(our_segmented), 
        Image.fromarray(opencv_segmented), 
        hist_image,
        f"Our Threshold: {our_threshold}\nOpenCV Threshold: {opencv_threshold}", 
    )
if __name__ == "__main__":
    #example usage
    # Ensure you have the image path set correctly
    image_path = '/home/akshat/projects/CSL7360_Project/bird.jpeg'  
    image = cv2.imread('/home/akshat/projects/CSL7360_Project/bird.jpeg') 
    # Call the function
    generate_segmented_image(image)



# # Optionally, save results to files
# cv2.imwrite("our_segmented.png", our_segmented)
# cv2.imwrite("opencv_segmented.png", opencv_segmented)