Here are the solutions to the questions from your assignment, kept simple, direct, and fulfilling
all requirements.
Question 1
Task: Write a Python function hist(img) that takes an image and returns an array of size 256
containing the count of pixels at each intensity level. Do not use [Link](). Plot the result using
[Link]().
import numpy as np
import [Link] as plt
from skimage import io, color
def hist(img):
# Ensure image is in 0-255 integer format
img_uint8 = np.uint8(img)
# Initialize an array of 256 zeros
histogram = [Link](256, dtype=int)
# Count occurrences of each pixel intensity
for pixel in img_uint8.flatten():
histogram[pixel] += 1
# Alternative 1: histogram, _ = [Link]([Link](), bins=256, range=[0, 256])
# Alternative 2: histogram = [Link]([Link](), minlength=256)
return histogram
# --- Execution ---
# img = color.rgb2gray([Link]('[Link]')) * 255
# h = hist(img)
# [Link](h)
# [Link]('Image Histogram')
# [Link]()
Question 2
Task: Apply a logarithmic point operation $s = c \cdot \log(1+r)$ to the image [Link].
Display the original and output images alongside their histograms. Explain the effect.
Python
import numpy as np
import [Link] as plt
from skimage import io
def log_transform(img):
# Calculate scaling constant 'c' to map the max value to 255
c = 255 / [Link](1 + [Link](img))
# Apply log transform
log_img = c * [Link](1 + img)
return log_img.astype(np.uint8)
# --- Execution ---
# img = [Link]('[Link]', as_gray=True) * 255
# out_img = log_transform(img)
# # Plotting
# fig, ax = [Link](2, 2, figsize=(10, 8))
# ax[0,0].imshow(img, cmap='gray'); ax[0,0].set_title('Original')
# ax[0,1].plot(hist(img)); ax[0,1].set_title('Original Histogram')
# ax[1,0].imshow(out_img, cmap='gray'); ax[1,0].set_title('Log Transformed')
# ax[1,1].plot(hist(out_img)); ax[1,1].set_title('Transformed Histogram')
# [Link]()
# EXPLANATION:
# The logarithmic transformation expands the values of dark pixels while
# compressing the higher-level (bright) values. This brings out hidden
# details in the darker regions of the image.
Question 3
Task: Write a function Contrast_stretching(img) that maps the minimum intensity to 0 and the
maximum to 255. Compare your output with [Link].rescale_intensity(). Display
images and histograms.
Python
import numpy as np
import [Link] as plt
from skimage import io, exposure
def Contrast_stretching(img):
min_val = [Link](img)
max_val = [Link](img)
# Apply linear stretching formula
stretched = (img - min_val) * (255.0 / (max_val - min_val))
return [Link](np.uint8)
# --- Execution ---
# img = [Link]('[Link]', as_gray=True) * 255
# my_output = Contrast_stretching(img)
# skimage_output = exposure.rescale_intensity(img, out_range=(0, 255)).astype(np.uint8)
# # Note: Visual comparison plots (using [Link] like above) go here.
# # Both functions will produce identical visual results and histograms,
# # effectively spreading the narrow intensity range across the full 0-255 spectrum.
Question 4
Task: Create a function power_law(img, gamma) to apply the power-law transformation. Test it
on [Link] using a $\gamma < 1$ and a $\gamma > 1$. Display original/output images and
histograms.
Python
import numpy as np
import [Link] as plt
from skimage import io
def power_law(img, gamma):
# Normalize image to 0.0 - 1.0 range first to prevent massive numbers
img_norm = img / 255.0
# Apply gamma
out_img = [Link](img_norm, gamma)
# Scale back to 0-255
return (out_img * 255).astype(np.uint8)
# --- Execution ---
# img = [Link]('[Link]', as_gray=True) * 255
# out_gamma_low = power_law(img, 0.5) # Gamma < 1: Brightens the image
# out_gamma_high = power_law(img, 2.0) # Gamma > 1: Darkens the image
# # Note: Plotting code for 3 images and 3 histograms goes here.
Problem 5
Task: Write a Python code that reads a gray image and computes its histogram. (Note: Using a
manual approach similar to the previous hist function).
Python
import numpy as np
import [Link] as plt
from skimage import io
# Load image as grayscale
img = [Link]('[Link]', as_gray=True)
img_uint8 = (img * 255).astype(np.uint8)
# Compute histogram
hist_values = [Link](256)
for pixel in img_uint8.flatten():
hist_values[pixel] += 1
# Alternative: hist_values = [Link](img_uint8.ravel(), minlength=256)
[Link](range(256), hist_values)
[Link]("Image Histogram")
[Link]()
Problem 6
Task: Write a Python code that reads a gray image and computes its normalized histogram
(Probability Mass Function).
Python
import numpy as np
from skimage import io
img = [Link]('[Link]', as_gray=True)
img_uint8 = (img * 255).astype(np.uint8)
# Normalized histogram = counts / total number of pixels
hist_counts = [Link](img_uint8.ravel(), minlength=256)
norm_hist = hist_counts / img_uint8.size
# Alternative: norm_hist, _ = [Link](img_uint8, bins=256, range=(0,256), density=True)
print(norm_hist)
Problem 7
Task: Write a Python code that reads a gray image and performs Histogram Equalization.
Python
import numpy as np
from skimage import io, exposure
import [Link] as plt
img = [Link]('[Link]', as_gray=True)
# Use skimage built-in for efficient equalization
img_eq = exposure.equalize_hist(img)
# Alternative: Manual calculation using CDF
# hist, bins = [Link]([Link](), 256, [0,1])
# cdf = [Link]()
# cdf_normalized = cdf / [Link]()
# img_eq = [Link]([Link](), bins[:-1], cdf_normalized).reshape([Link])
[Link](img_eq, cmap='gray')
[Link]()
Problem 8
Task: Write a Python code that reads an image and converts it to a binary image using a global
threshold $T=120$.
Python
import numpy as np
from skimage import io
img = [Link]('[Link]', as_gray=True)
img_uint8 = (img * 255).astype(np.uint8)
T = 120
# Create binary mask: pixels > T become 1 (White), others 0 (Black)
binary_img = (img_uint8 > T).astype(np.uint8) * 255
# Alternative: binary_img = [Link](img_uint8 > T, 255, 0)
[Link](binary_img, cmap='gray')
Problem 9
Task: Write a Python code that performs automatic thresholding using Otsu's method.
Python
from skimage import io, filters
import [Link] as plt
img = [Link]('[Link]', as_gray=True)
# Find optimal threshold using Otsu
thresh = filters.threshold_otsu(img)
binary = img > thresh
# Alternative using OpenCV: _, binary = [Link](img, 0, 255, cv2.THRESH_BINARY +
cv2.THRESH_OTSU)
[Link](binary, cmap='gray')
[Link](f"Otsu Threshold: {thresh:.2f}")
[Link]()
Problem 10
Task: Write a Python code that applies a $3 \times 3$ mean filter (box filter) to a gray image.
Python
import numpy as np
from skimage import io
from [Link] import convolve2d
img = [Link]('[Link]', as_gray=True)
# Define 3x3 mean kernel
kernel = [Link]((3, 3)) / 9
# Apply convolution
smooth_img = convolve2d(img, kernel, mode='same')
# Alternative: from [Link] import rank; smooth_img = [Link](img, [Link]((3,3)))
[Link](smooth_img, cmap='gray')
Problem 11
Task: Write a Python code that applies a Laplacian filter using the following kernel:
$\begin{bmatrix} 0 & -1 & 0 \\ -1 & 4 & -1 \\ 0 & -1 & 0 \end{bmatrix}$
Python
import numpy as np
from skimage import io
from [Link] import convolve2d
img = [Link]('[Link]', as_gray=True)
# Define Laplacian kernel
kernel = [Link]([[0, -1, 0],
[-1, 4, -1],
[0, -1, 0]])
# Highlight details/edges
laplacian_img = convolve2d(img, kernel, mode='same')
# Note: Results may contain negative values; clipping or normalization is often needed for
display
[Link]([Link](laplacian_img, 0, 1), cmap='gray')
Problem 12
Task: Write a Python code that shifts the pixels of an image using appropriate filters by 2 pixels
to the left and 3 pixels to the bottom.
Python
import numpy as np
from skimage import io
from [Link] import convolve2d
img = [Link]('[Link]', as_gray=True)
# To shift left by 2 and down by 3, the '1' in the kernel
# must be at index [row_shift, col_shift] in a kernel of appropriate size.
# For a 7x7 kernel, the center is [3,3].
# Shift left 2 -> col 1. Shift down 3 -> row 6.
kernel = [Link]((7, 7))
kernel[6, 1] = 1
shifted_img = convolve2d(img, kernel, mode='same')
# Alternative: shifted_img = [Link](img, (3, -2), axis=(0, 1))
[Link](shifted_img, cmap='gray')
Problem 13 & 14
Task: Write a Python code that shifts pixels 2 to the left and generates a new image by
averaging the original image with the shifted image.
Python
import numpy as np
from skimage import io
img = [Link]('[Link]', as_gray=True)
# Shift left by 2 pixels using [Link]
shifted = [Link](img, -2, axis=1)
# Average the two images
out_img = (img + shifted) / 2.0
# Alternative: out_img = 0.5 * img + 0.5 * shifted
[Link](out_img, cmap='gray')
Problem 15
Task: Apply point operations successively: $0.9 \times x$, then $(\frac{x}{255})^{1/3} \times
255$.
Python
import numpy as np
from skimage import io
img = [Link]('[Link]', as_gray=True)
# Operation 1: Multiply by 0.9 (Darkening)
step1 = img * 0.9
# Operation 2: Power-law (Gamma = 1/3)
# Note: Input must be in 0-1 range for the power law formula provided
step2 = [Link](step1, 1/3) * 255
# Alternative: step2 = ((step1)**(1/3)) * 255
[Link]([Link](np.uint8), cmap='gray')
Problem 16
Task: Apply a specific convolution kernel (A sharpening/edge-related mask).
Python
import numpy as np
from skimage import io
from [Link] import convolve2d
img = [Link]('[Link]', as_gray=True)
# Define the kernel from the problem description
kernel = [Link]([[0, 0, 0],
[-1/9, 2, -1/9],
[0, 0, 0]])
out_img = convolve2d(img, kernel, mode='same')
[Link]([Link](out_img, 0, 1), cmap='gray')
Problem 17
Task: Filter with a Gaussian filter, then find edges using the Sobel operator in both directions.
Python
from skimage import io, filters, feature
import [Link] as plt
img = [Link]('[Link]', as_gray=True)
# Step 1: Gaussian Blur
blurred = [Link](img, sigma=1)
# Step 2: Sobel Edges (Magnitude combines both directions)
edges = [Link](blurred)
# Alternative:
# edge_h = filters.sobel_h(blurred)
# edge_v = filters.sobel_v(blurred)
# edges = [Link](edge_h**2 + edge_v**2)
[Link](edges, cmap='gray')
[Link]()
Problem 18
Task: Generate a $9 \times 9$ Laplacian of Gaussian (LoG) filter.
Python
import numpy as np
from scipy import ndimage
import [Link] as plt
# Create a 9x9 grid
size = 9
sigma = 1.5
x, y = [Link][-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1]
# Mathematical formula for LoG
log_kernel = -(1 / ([Link] * sigma**4)) * (1 - (x**2 + y**2) / (2 * sigma**2)) * [Link](-(x**2 + y**2) /
(2 * sigma**2))
# Alternative:
# kernel = [Link]((9, 9)); kernel[4, 4] = 1
# log_kernel = ndimage.gaussian_laplace(kernel, sigma=sigma)
[Link](log_kernel, cmap='gray')
[Link]("9x9 LoG Filter")
[Link]()
[Link]()