IMAGE PROCESSING Image Enhancement in spatial domain: Hours: Basic Gray Level Transformation functions – Image Negatives, Log Transformations, Power- Law Transformations. Piecewise-Linear Transformation Functions: Contrast Stretching, Gray Level Slicing, Bit Plane Slicing, Histogram Processing–Equalization, Specification. Basics of Spatial Filtering – Smoothing: Smoothing Linear Filters, Ordered Statistic Filters, Sharpening: Laplacian, Unsharp Masking and High Boost Filtering

 

 IMAGE PROCESSING

Unit III -Image Enhancement in spatial domain:

Covered Topic:Image Enhancement in spatial domain: Hours: Basic Gray Level Transformation functions – Image Negatives, Log Transformations, Power- Law Transformations. Piecewise-Linear Transformation Functions: Contrast Stretching, Gray Level Slicing, Bit Plane Slicing, Histogram Processing–Equalization, Specification. Basics of Spatial Filtering – Smoothing: Smoothing Linear Filters, Ordered Statistic Filters, Sharpening: Laplacian, Unsharp Masking and High Boost Filtering 


Basic Gray Level Transformation functions :

Gray level transformation functions, also known as intensity transformation functions, are fundamental in image processing. These functions are used to enhance or modify the pixel intensities of an image, improving its visual quality or emphasizing certain features. Here are some basic gray level transformation functions:


1. **Linear Transformation:**

   - Function Form:

     g(x,y)=af(x,y)+b


   - Description:

     Linear transformation scales and shifts pixel intensities. Parameters \(a\) and \(b\) control the slope and intercept of the line, respectively. It is used for contrast stretching and brightness adjustment.


2. **Logarithmic Transformation:**

   - Function Form:

    g(x,y)=clog(1+f(x,y))

   - Description:

     Logarithmic transformation enhances the details in the darker regions of an image. The parameter c adjusts the contrast. It is particularly useful when dealing with images with a wide range of intensity values.


3. **Power-Law (Gamma) Transformation:**

   - **Function Form:**

g(x,y)=c[f(x,y)]γ


   - **Description:**

     Power-law transformation adjusts the image gamma to control the overall brightness and contrast. The parameters c and gamma γ influence the contrast and brightness, respectively.


4. **Histogram Equalization:**

   - **Function Form:**

    g(x,y)=T[f(x,y)]

   - **Description:**

     Histogram equalization enhances the contrast of an image by spreading the pixel intensities across the entire dynamic range. It is particularly effective in improving the visibility of details in images with low contrast.


5. **Thresholding:**

   - **Function Form:**

   0 & \text{if } f(x, y) < T \\

255 & \text{if } f(x, y) \geq T

   \end{cases} \]

   - **Description:**

     Thresholding is a binary transformation that segments an image into two regions based on a predefined threshold \(T\). Pixels with intensities below \(T\) are set to 0, and those above \(T\) are set to 255 (or 1 in normalized scale).


6. **Piecewise Linear Transformation:**

   - **Function Form:**

    a_1 \cdot f(x, y) + b_1 & \text{if } f(x, y) < T_1 \\

a_2 \cdot f(x, y) + b_2 & \text{if } T_1 \leq f(x, y) < T_2 \\ a_3 \cdot f(x, y) + b_3 & \text{if } f(x, y) \geq T_2

   \end{cases} \]

   - **Description:**

     Piecewise linear transformation allows different linear functions to be applied to different intensity ranges. This is useful for adjusting contrast and brightness in specific regions of the image.


These basic gray level transformation functions form the foundation for more complex image enhancement techniques. Depending on the characteristics of the image and the desired result, different transformations can be applied to achieve the desired visual quality or analysis outcome.


Image Negatives:

The image negative, also known as inverse or complement, is a basic gray level transformation that produces the photographic negative of an image. In this transformation, the intensities of the pixels are inverted, such that dark areas become bright, and vice versa. The formula for computing the negative of an image is straightforward:


g(x,y)=L1f(x,y)


where:

- g(x, y)  is the intensity of the pixel in the negative image.

- f(x, y)  is the intensity of the corresponding pixel in the original image.

- L  is the maximum intensity level (for example, 256 for an 8-bit image).


Characteristics and Effects:


1. **Inversion of Intensity:**

   - Dark pixels become bright, and bright pixels become dark in the negative image.


2. **Contrast Enhancement:**

   - The negative transformation often enhances the contrast of the image, making details more visible.


3. **Simple Implementation:**

   - Computation of the negative is a simple operation, requiring only subtraction and inversion.


4. **Application in Photography:**

   - The concept of image negatives originates from traditional film photography, where the negative is used to produce positive prints.


5. **Histogram Properties:**

   - The histogram of the negative image is the complement of the original histogram, with peaks becoming valleys and vice versa.


Mathematical Explanation:


The formula g(x,y)=L1f(x,y) can be understood as follows:

-  L - 1  represents the maximum intensity level in the image.

- Subtracting  f(x, y)  inverts the intensity values.

- The result is a pixel intensity in the negative image.


Implementation in Python:


Here is a simple example of how to implement the image negative transformation in Python using the popular image processing library, OpenCV:


-----------------------------------------------------------------------------------------------------------------------------

python code


import cv2

import numpy as np


# Read the image

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Compute the negative image

negative_image = 255 - original_image


# Display the original and negative images

cv2.imshow('Original Image', original_image)

cv2.imshow('Negative Image', negative_image)

cv2.waitKey(0)

cv2.destroyAllWindows()

-----------------------------------------------------------------------------------------------------------------------------

In this example, the `cv2.imread` function is used to read an image in grayscale mode. The negative image is then computed using the formula \( 255 - \text{{original\_image}} \) and displayed using `cv2.imshow`.

Log Transformations :

Log transformations are a type of gray level transformation used in image processing to enhance the details in the darker regions of an image. These transformations are particularly useful when dealing with images that have a wide range of intensity values, especially when the details in the darker areas are not clearly visible. Logarithmic transformations are applied to stretch the intensity values, making the darker details more distinguishable.

Mathematical Representation:

The general form of a logarithmic transformation is given by:

g(x,y)=clog(1+f(x,y))

where:

-  g(x, y)  is the intensity of the pixel in the transformed image.

-  f(x, y)  is the intensity of the corresponding pixel in the original image.

-  c  is a constant that controls the contrast of the transformation.


Characteristics and Effects:


1. **Enhancement of Darker Details:**

   - Log transformations primarily enhance the details in the darker regions of an image.


2. **Nonlinear Stretching:**

   - The logarithmic function provides a nonlinear stretching of intensity values, resulting in a more balanced and visually appealing image.


3. **Contrast Adjustment:**

   - The transformation is particularly effective when the image has a wide range of intensity values, and the details in the darker areas need to be emphasized.


4. **Smoothing Effect:**

   - Log transformations can also have a smoothing effect on images, reducing the impact of noise in low-intensity regions.


Implementation in Python:


Here is an example of how to implement a log transformation in Python using the NumPy and OpenCV libraries:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Apply a log transformation

c = 255 / np.log(1 + np.max(original_image))

log_transformed = c * np.log1p(original_image)


# Convert to uint8 (required for display)

log_transformed = np.uint8(log_transformed)


# Display the original and log-transformed images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(log_transformed, cmap='gray'), plt.title('Log-Transformed Image')

plt.show()

```


In this example, the logarithmic transformation is applied to the pixel values using the formula log(1+original_image). The constant is calculated to ensure that the transformed image has intensity values in the range [0, 255]. The result is then displayed alongside the original image using Matplotlib.


Power- Law Transformations.

Power-law transformations, also known as gamma corrections, are a type of gray level transformation used in image processing to adjust the overall brightness and contrast of an image. These transformations involve raising the pixel intensities to a power, introducing a nonlinearity that can be used to enhance or suppress certain intensity ranges. The general form of a power-law transformation is given by:


g(x,y)=c[f(x,y)]γ


where:

  • (,) is the intensity of the pixel in the transformed image.
  • (,) is the intensity of the corresponding pixel in the original image.
  • is a constant that controls the overall brightness of the transformation.
  • is the gamma parameter that controls the contrast of the transformation.

Characteristics and Effects:


1. **Contrast Adjustment:**

   - The gamma parameter  ()  allows for flexible contrast adjustment. Values less than 1 enhance contrast in the lower intensity range, while values greater than 1 enhance contrast in the higher intensity range.


2. **Brightness Control:**

   - The constant c  controls the overall brightness of the image. Adjusting this constant allows for brightness enhancement or reduction.


3. **Nonlinear Stretching:**

   - Power-law transformations provide nonlinear stretching of intensity values, allowing for fine-tuning of the image appearance.


4. **Gamma Correction in Display Devices:**

   - Gamma correction is commonly used in display devices to ensure that the displayed image matches the perceived brightness by the human eye.


Mathematical Representation:


The formula  (,)=[(,)] can be implemented in various programming languages, and the constants c  and γ can be adjusted based on the desired transformation.


 Implementation in Python:


Here's an example of implementing a power-law transformation in Python using NumPy and OpenCV:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Power-law transformation parameters

gamma = 0.5

c = 1


# Apply a power-law transformation

power_law_transformed = c * (original_image ** gamma)


# Clip the values to ensure they are in the valid range [0, 255]

power_law_transformed = np.clip(power_law_transformed, 0, 255)


# Convert to uint8 (required for display)

power_law_transformed = np.uint8(power_law_transformed)


# Display the original and power-law transformed images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(power_law_transformed, cmap='gray'), plt.title('Power-Law Transformed Image')

plt.show()

```


In this example, the power-law transformation is applied using the formula  [(,)], and the resulting image is displayed alongside the original image using Matplotlib. Adjust the values of γ and   based on your specific requirements.


Piecewise-Linear Transformation Functions:

Piecewise-linear transformation functions are a type of gray level transformation used in image processing to adjust the contrast and brightness of an image in different intensity ranges. Instead of applying a single linear function to the entire range of pixel intensities, piecewise-linear transformations involve using multiple linear functions, each applied to a specific intensity range. This allows for more localized control over the enhancement or suppression of certain details in an image.


### Mathematical Representation:


The general form of a piecewise-linear transformation function can be expressed as follows:


\[ g(x, y) = \begin{cases}

a_1 \cdot f(x, y) + b_1 & \text{if } f(x, y) < T_1 \\

a_2 \cdot f(x, y) + b_2 & \text{if } T_1 \leq f(x, y) < T_2 \\

\vdots \\

a_n \cdot f(x, y) + b_n & \text{if } f(x, y) \geq T_n

\end{cases} \]


where:

- \( g(x, y) \) is the intensity of the pixel in the transformed image.

- \( f(x, y) \) is the intensity of the corresponding pixel in the original image.

- \( a_i \) and \( b_i \) are the slope and intercept of the linear function applied in the \(i\)-th intensity range.

- \( T_i \) are the threshold values that define the boundaries between intensity ranges.


### Characteristics and Effects:


1. **Localized Control:**

   - Piecewise-linear transformations provide localized control over the contrast and brightness of different intensity ranges in an image.


2. **Adaptability:**

   - Different slopes and intercepts in each segment allow for adaptability to the specific characteristics of the image.


3. **Enhancement in Specific Ranges:**

   - Details in specific intensity ranges can be enhanced or suppressed based on the parameters chosen for each segment.


4. **Smooth Transition:**

   - To avoid abrupt changes in the appearance of the image, the transition between segments is typically designed to be smooth.


### Implementation in Python:


Here's a simplified example of how to implement a piecewise-linear transformation in Python using NumPy and Matplotlib:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Define piecewise-linear transformation parameters

T1 = 100

T2 = 150

a1, b1 = 1, 0

a2, b2 = 2, -100

a3, b3 = 1, 50


# Apply piecewise-linear transformation

transformed_image = np.piecewise(original_image, [original_image < T1, (T1 <= original_image) & (original_image < T2), original_image >= T2],

                                  [lambda x: a1 * x + b1, lambda x: a2 * x + b2, lambda x: a3 * x + b3])


# Convert to uint8 (required for display)

transformed_image = np.uint8(transformed_image)


# Display the original and transformed images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(transformed_image, cmap='gray'), plt.title('Piecewise-Linear Transformed Image')

plt.show()

```


In this example, different linear functions are applied to three intensity ranges defined by the thresholds \(T_1\) and \(T_2\). You can adjust the parameters based on the characteristics of your specific image.

Contrast Stretching:

Contrast stretching, also known as normalization or intensity rescaling, is a common gray level transformation used in image processing to enhance the contrast of an image. The goal is to stretch the range of pixel intensities in an image to cover the full dynamic range (0 to 255 for an 8-bit image). This process helps reveal more details and make the image visually appealing by utilizing the entire available intensity spectrum.


Mathematical Representation:

The contrast stretching operation is typically represented by a linear transformation:

(,)=(,)minmaxmin×(new_maxnew_min)+new_min

where:

  • (,) is the intensity of the pixel in the transformed image.
  • (,) is the intensity of the corresponding pixel in the original image.
  • min and max are the minimum and maximum intensities in the original image.
  • new_min and new_max are the desired minimum and maximum intensities in the transformed image.


### Characteristics and Effects:


1. **Contrast Enhancement:**

   - Contrast stretching aims to enhance the contrast of the image by utilizing the full available intensity range.


2. **Improved Visibility:**

   - Details that were previously obscured due to limited intensity range become more visible after contrast stretching.


3. **Simple and Effective:**

   - It is a straightforward and effective technique, applicable in various scenarios without complex adjustments.


4. **Normalization to Full Range:**

   - The operation normalizes the intensity values to cover the entire dynamic range, making it suitable for display and analysis.


### Implementation in Python:


Here's a simple example of implementing contrast stretching in Python using NumPy and Matplotlib:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Perform contrast stretching

new_min = 0

new_max = 255

min_val = np.min(original_image)

max_val = np.max(original_image)


contrast_stretched = ((original_image - min_val) / (max_val - min_val)) * (new_max - new_min) + new_min


# Convert to uint8 (required for display)

contrast_stretched = np.uint8(contrast_stretched)


# Display the original and contrast-stretched images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(contrast_stretched, cmap='gray'), plt.title('Contrast-Stretched Image')

plt.show()

```


In this example, the pixel intensities are linearly transformed to stretch the contrast to the full range [0, 255]. Adjust the values of `new_min` and `new_max` based on your specific requirements.

Gray Level Slicing:

Gray level slicing, also known as intensity slicing or thresholding, is a gray level transformation technique used in image processing to highlight specific intensity ranges in an image while suppressing others. This method is particularly useful for emphasizing certain features within a specific intensity band, making them more visually prominent.


### Mathematical Representation:


The general form of gray level slicing involves segmenting the intensity levels into different ranges and modifying the pixel values within those ranges. The operation can be expressed as follows:


\[ g(x, y) = \begin{cases}

  \text{{new\_value\_inside\_range}}, & \text{{if }} \text{{lower\_threshold}} \leq f(x, y) \leq \text{{upper\_threshold}} \\

  f(x, y), & \text{{otherwise}}

\end{cases} \]


where:

- \( g(x, y) \) is the intensity of the pixel in the transformed image.

- \( f(x, y) \) is the intensity of the corresponding pixel in the original image.

- \(\text{{lower\_threshold}}\) and \(\text{{upper\_threshold}}\) define the range of intensities to be emphasized.


### Characteristics and Effects:


1. **Highlighting Specific Intensity Range:**

   - Gray level slicing enhances specific intensity ranges while keeping other regions unchanged.


2. **Suppressing Irrelevant Information:**

   - Intensity levels outside the specified range are suppressed, making it easier to focus on particular features.


3. **Simple Image Enhancement:**

   - Gray level slicing is a straightforward method for emphasizing certain details in an image.


### Implementation in Python:


Here's a simple example of implementing gray level slicing in Python using NumPy and Matplotlib:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Define gray level slicing parameters

lower_threshold = 100

upper_threshold = 200

new_value_inside_range = 255


# Apply gray level slicing

gray_level_sliced = np.copy(original_image)

gray_level_sliced[(original_image >= lower_threshold) & (original_image <= upper_threshold)] = new_value_inside_range


# Display the original and gray level sliced images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(gray_level_sliced, cmap='gray'), plt.title('Gray Level Sliced Image')

plt.show()

```


In this example, intensity values within the specified range \([ \text{{lower\_threshold}}, \text{{upper\_threshold}} ]\) are set to `new_value_inside_range`. Adjust the threshold values and the new value based on your specific image and enhancement requirements.


Bit Plane Slicing

Bit plane slicing is a technique used in image processing to extract specific bit planes from the binary representation of pixel values in a digital image. In a grayscale image, each pixel is typically represented by 8 bits (for an 8-bit image), and bit plane slicing involves isolating and visualizing the contribution of individual bits to the overall pixel intensity. This technique is useful for analyzing the significance of each bit in representing image details.


### Mathematical Representation:


Let \( f(x, y) \) represent the intensity of a pixel at coordinates \((x, y)\) in the original image, where \( f \) is an 8-bit pixel value (ranging from 0 to 255). The binary representation of \( f \) can be written as \( b_7b_6b_5b_4b_3b_2b_1b_0 \), where each \( b_i \) is a binary bit.


Bit plane slicing isolates the contribution of a specific bit by setting all other bits to zero:


\[ g(x, y) = b_i \times 2^i \]


where:

- \( g(x, y) \) is the intensity of the pixel in the bit plane-sliced image.

- \( b_i \) is the value of the \(i\)-th bit in the binary representation of \( f(x, y) \).

- \( i \) is the bit plane index (0 to 7 for an 8-bit image).


### Characteristics and Effects:


1. **Visualization of Bit Significance:**

   - Bit plane slicing allows visualizing the contribution of each bit to the overall pixel intensity, helping to understand the significance of each bit.


2. **Image Analysis:**

   - Analyzing individual bit planes can reveal hidden patterns or details in the image, especially in the context of binary image processing.


3. **Enhancement and Compression:**

   - Some applications involve selectively enhancing or compressing certain bit planes to achieve specific visual effects.


### Implementation in Python:


Here's an example of implementing bit plane slicing in Python using NumPy and Matplotlib:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Perform bit plane slicing for the 3rd bit (index 2)

bit_plane_index = 2

bit_plane_sliced = (original_image >> bit_plane_index) & 1


# Display the original and bit plane sliced images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(bit_plane_sliced, cmap='gray'), plt.title('Bit Plane Sliced Image (Bit 2)')

plt.show()

```


In this example, the 3rd bit plane (index 2) is extracted, and the resulting image is displayed alongside the original image. Adjust the `bit_plane_index` parameter to visualize different bit planes.


Histogram Processing–Equalization:

Histogram equalization is a technique used in image processing to enhance the contrast of an image by redistributing the intensities in the histogram. The goal is to achieve a uniform distribution of pixel intensities across the entire dynamic range. This process is particularly effective when an image has a narrow or non-uniform distribution of intensity values.


### Mathematical Representation:


Let \( f(x, y) \) represent the intensity of a pixel at coordinates \((x, y)\) in the original image. The histogram equalization transformation is given by:


\[ g(x, y) = T[f(x, y)] \]


where:

- \( g(x, y) \) is the intensity of the pixel in the equalized image.

- \( T[] \) is the transformation function.


The transformation function \( T[] \) is defined as:


\[ T[i] = \frac{{L - 1}}{{M \times N}} \sum_{j=0}^{i} n_j \]


where:

- \( L \) is the number of intensity levels (typically 256 for an 8-bit image).

- \( M \) and \( N \) are the dimensions of the image.

- \( n_j \) is the cumulative histogram up to intensity level \( j \).


### Characteristics and Effects:


1. **Contrast Enhancement:**

   - Histogram equalization enhances the contrast of an image by redistributing intensities across the entire range.


2. **Brightness Normalization:**

   - It helps normalize the brightness, making details more visible.


3. **Adaptive Nature:**

   - Histogram equalization adapts to the specific characteristics of the image, enhancing local details.


4. **Avoiding Saturation:**

   - Unlike some other contrast enhancement techniques, histogram equalization avoids intensity saturation.


### Implementation in Python:


Here's an example of implementing histogram equalization in Python using OpenCV and Matplotlib:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Apply histogram equalization

equalized_image = cv2.equalizeHist(original_image)


# Display the original and equalized images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(equalized_image, cmap='gray'), plt.title('Equalized Image')

plt.show()

```


In this example, the `cv2.equalizeHist()` function is used to perform histogram equalization on the original image. The resulting equalized image is then displayed alongside the original image. This simple implementation in OpenCV takes care of the transformation function and cumulative histogram calculations.


Specification

Specification in the context of image processing generally refers to the process of defining or specifying a desired histogram or statistical distribution for an image and then transforming the image to match that specification. This is often done to achieve a particular desired visual appearance or to match a certain statistical characteristic.



Specification in the context of image processing generally refers to the process of defining or specifying a desired histogram or statistical distribution for an image and then transforming the image to match that specification. This is often done to achieve a particular desired visual appearance or to match a certain statistical characteristic.

Mathematical Representation:

Let (,) represent the intensity of a pixel at coordinates (,) in the original image, and (,) be the intensity of the pixel in the transformed (specified) image. The specification process involves defining a transformation function () such that:

(,)=[(,)]

The transformation function () is designed to achieve a specified histogram or statistical distribution.


### Characteristics and Effects:


1. **Customizing Histogram:**

   - Specification allows for customizing the histogram or statistical distribution of an image to meet specific requirements.


2. **Matching Reference Histogram:**

   - In some cases, the specification involves matching the histogram of the original image to a reference histogram.


3. **Contrast Adjustment:**

   - The process can be used for contrast adjustment, emphasizing certain intensity ranges.


### Implementation in Python:


Implementing histogram specification involves defining a transformation function based on the desired specification and then applying it to the original image. Here's a general example using NumPy and Matplotlib:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Define a desired histogram (for illustration purposes)

desired_histogram = np.array([0, 10, 30, 50, 70, 90, 110, 130, 150, 170, 190, 210, 230, 255])


# Calculate the cumulative distribution function (CDF) of the original image

cdf_original = np.cumsum(np.histogram(original_image.flatten(), bins=256, range=[0, 256])[0])


# Calculate the CDF of the desired histogram

cdf_desired = np.cumsum(desired_histogram)


# Map the original image intensities to the desired histogram using linear interpolation

mapping_function = np.interp(original_image.flatten(), np.arange(256), cdf_desired)


# Reshape the transformed intensities back to the original image shape

specified_image = mapping_function.reshape(original_image.shape)


# Display the original and specified images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(specified_image, cmap='gray'), plt.title('Specified Image')

plt.show()

```


In this example, the `desired_histogram` array represents a desired histogram. The code then calculates the cumulative distribution functions (CDFs) of the original image and the desired histogram. Finally, it uses linear interpolation to map the original image intensities to the specified histogram. This is a basic illustration, and the actual implementation may vary depending on the specific requirements of the histogram specification.

Basics of Spatial Filtering – Smoothing:

Spatial filtering, specifically smoothing or blurring, is a fundamental operation in image processing. It involves applying a filter or kernel to the pixels of an image to achieve a smoothing effect. Smoothing is commonly used to reduce noise, eliminate fine details, and create a more visually appealing or simplified representation of an image.


Mathematical Representation:

Let (,) represent the intensity of a pixel at coordinates (,) in the original image. The smoothed image (,) is obtained by convolving the original image with a smoothing filter kernel (,):

(,)===(,)(+,+)

where:

  • (,) is the smoothing filter kernel.
  • and are the half-widths of the filter kernel in the horizontal and vertical directions.

### Characteristics and Effects:


1. **Noise Reduction:**

   - Spatial smoothing helps reduce the effects of noise in an image, particularly high-frequency noise.


2. **Blur and Smoothing:**

   - The process introduces a blur or smoothing effect, making the image appear less sharp and reducing fine details.


3. **Averaging and Weighted Averaging:**

   - Common smoothing filters involve averaging or weighted averaging of pixel values within a neighborhood.


### Types of Smoothing Filters:


1. **Box Filter:**

   - A simple averaging filter where all coefficients are equal.


2. **Gaussian Filter:**

   - A weighted averaging filter that gives more importance to central pixels.


3. **Median Filter:**

   - Takes the median value of pixels in the neighborhood, useful for preserving edges.


4. **Bilateral Filter:**

   - Considers both spatial and intensity differences for more selective smoothing.


### Implementation in Python (Box Filter):


Here's a simple example of implementing spatial smoothing using a box filter in Python with OpenCV:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Apply a box filter for spatial smoothing

box_filter_size = (5, 5)

smoothed_image = cv2.boxFilter(original_image, ddepth=-1, ksize=box_filter_size)


# Display the original and smoothed images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(smoothed_image, cmap='gray'), plt.title('Smoothed Image (Box Filter)')

plt.show()

```


In this example, `cv2.boxFilter` is used to apply a box filter for spatial smoothing. The `ksize` parameter determines the size of the filter kernel, and larger values result in stronger smoothing. Adjust the filter size based on your specific requirements.


Smoothing Linear Filters:


Smoothing linear filters are commonly used in image processing to achieve a blur or smoothing effect by averaging or weighted averaging pixel values in the image. These filters are applied to reduce noise, eliminate fine details, and create a more visually appealing or simplified representation of an image.


### Types of Smoothing Linear Filters:


1. **Box Filter (Averaging Filter):**

   - A simple filter where all coefficients are equal, resulting in uniform averaging of pixel values within the filter window.


2. **Gaussian Filter:**

   - A weighted averaging filter that gives more importance to central pixels and follows a Gaussian distribution. It provides a smoother transition between neighboring pixels.


3. **Median Filter:**

   - Takes the median value of pixel intensities within a neighborhood. It is particularly effective in preserving edges while reducing noise.


4. **Bilateral Filter:**

   - Considers both spatial and intensity differences for more selective smoothing. It preserves edges while smoothing regions with similar intensities.


Mathematical Representation (Box Filter):

Let (,) represent the intensity of a pixel at coordinates (,) in the original image. The smoothed image (,) using a box filter is obtained by averaging pixel values within a window:

(,)=1(2+1)(2+1)==(+,+)

where:

  • and are the half-widths of the filter kernel in the horizontal and vertical directions.


### Implementation in Python (Gaussian Filter):


Here's an example of implementing spatial smoothing using a Gaussian filter in Python with OpenCV:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Apply a Gaussian filter for spatial smoothing

gaussian_filter_size = (5, 5)

smoothed_image = cv2.GaussianBlur(original_image, ksize=gaussian_filter_size, sigmaX=0)


# Display the original and smoothed images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(smoothed_image, cmap='gray'), plt.title('Smoothed Image (Gaussian Filter)')

plt.show()

```


In this example, `cv2.GaussianBlur` is used to apply a Gaussian filter for spatial smoothing. The `ksize` parameter determines the size of the filter kernel, and `sigmaX` controls the standard deviation of the Gaussian distribution. Adjust these parameters based on your specific requirements.

Ordered Statistic Filters: 

Ordered statistic filters, also known as rank filters or percentile filters, are a class of non-linear filters used in image processing to perform operations based on the ordering or ranking of pixel values within a local neighborhood. These filters are particularly effective in preserving edges and details while reducing noise.


### Characteristics and Operation:


1. **Ranking Pixel Values:**

   - Ordered statistic filters rank pixel values within a local window and apply an operation based on their order.


2. **Non-linear Operation:**

   - Unlike linear filters, ordered statistic filters perform a non-linear operation, making them suitable for tasks like noise reduction while preserving edges.


3. **Robust to Outliers:**

   - These filters are robust to outliers because they operate based on the rank or order of pixel values, not their absolute magnitudes.


### Types of Ordered Statistic Filters:


1. **Median Filter:**

   - The simplest ordered statistic filter, where the central pixel in the local neighborhood is replaced with the median value. Effective in reducing salt-and-pepper noise.


2. **Min Filter:**

   - Replaces the central pixel with the minimum value in the local neighborhood. Useful for reducing salt noise.


3. **Max Filter:**

   - Replaces the central pixel with the maximum value in the local neighborhood. Useful for reducing pepper noise.


4. **Midpoint Filter:**

   - Replaces the central pixel with the midpoint (average) of the minimum and maximum values in the local neighborhood.


5. **Alpha-Trimmed Mean Filter:**

   - Computes the mean after removing a specified number of smallest and largest pixel values in the local neighborhood.


### Mathematical Representation (Median Filter):


Let \( f(x, y) \) represent the intensity of a pixel at coordinates \((x, y)\) in the original image. The median filter replaces the central pixel value \( f(x, y) \) with the median value of the pixel intensities in the local neighborhood:


\[ g(x, y) = \text{{median}}\left\{ f(x+i, y+j) \,|\, -a \leq i \leq a, -b \leq j \leq b \right\} \]


where:

- \( a \) and \( b \) are the half-widths of the filter window in the horizontal and vertical directions.


### Implementation in Python (Median Filter):


Here's an example of implementing a median filter in Python with OpenCV:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Apply a median filter

median_filter_size = 5

filtered_image = cv2.medianBlur(original_image, ksize=median_filter_size)


# Display the original and filtered images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(filtered_image, cmap='gray'), plt.title('Filtered Image (Median Filter)')

plt.show()

```


In this example, `cv2.medianBlur` is used to apply a median filter for noise reduction. The `ksize` parameter determines the size of the filter window. Adjust this parameter based on your specific requirements.


Sharpening: Laplacian

Laplacian sharpening is a technique used in image processing to enhance fine details and emphasize edges in an image. It involves applying the Laplacian operator to the original image, which highlights areas of rapid intensity change. This can be achieved by subtracting the original image from the result of a convolution with the Laplacian kernel.


Laplacian Operator:

The Laplacian operator is a second-order derivative filter that calculates the sum of second partial derivatives of the image intensity. In discrete form, the 3x3 Laplacian kernel is commonly used:

Laplacian Kernel=[010141010]

Mathematical Representation:

Let (,) represent the intensity of a pixel at coordinates (,) in the original image. The sharpened image (,) is obtained by adding the Laplacian of (,) to the original image:

(,)=(,)+Laplacian[(,)]

where:

  • is a scaling factor that controls the strength of the sharpening effect.


### Characteristics and Effects:


1. **Edge Enhancement:**

   - Laplacian sharpening enhances edges and fine details in an image.


2. **Increased Noise:**

   - The sharpening process may amplify noise in the image.


3. **Controlled by Scaling Factor:**

   - The scaling factor \( k \) allows control over the strength of the sharpening effect.


### Implementation in Python:


Here's an example of implementing Laplacian sharpening in Python with OpenCV:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Apply Laplacian sharpening

laplacian_image = cv2.Laplacian(original_image, cv2.CV_64F)

sharpened_image = original_image - 0.5 * laplacian_image


# Clip values to ensure they are in the valid intensity range [0, 255]

sharpened_image = np.clip(sharpened_image, 0, 255).astype(np.uint8)


# Display the original and sharpened images

plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 2, 2), plt.imshow(sharpened_image, cmap='gray'), plt.title('Sharpened Image (Laplacian)')

plt.show()

```


In this example, `cv2.Laplacian` is used to calculate the Laplacian of the original image, and then the sharpened image is obtained by subtracting a scaled version of the Laplacian from the original image. Adjust the scaling factor based on the desired level of sharpening.


Unsharp Masking and High Boost Filtering


Unsharp masking and high-boost filtering are image enhancement techniques that involve the application of a sharpening filter to an image. These methods are particularly effective in enhancing edges and fine details. Both techniques utilize the concept of subtracting a blurred version of the original image from the original image itself.


Unsharp Masking:

  1. Blurring the Original Image:

    • A blurred version of the original image is created using a low-pass filter (e.g., Gaussian filter).
  2. Subtracting the Blurred Image:

    • The blurred image is subtracted from the original image, resulting in an "unsharp" mask that emphasizes the high-frequency components.
  3. Adding the Unsharp Mask:

    • The unsharp mask is added back to the original image, enhancing edges and fine details.

High-Boost Filtering:

  1. Blurring the Original Image:

    • Similar to unsharp masking, a blurred version of the original image is created.
  2. Scaling and Subtracting the Blurred Image:

    • The blurred image is scaled by a factor (often greater than 1) and then subtracted from the original image.
  3. Adding the High-Boost Filter:

    • The high-boost filter is added back to the original image, resulting in enhanced edges and fine details.

Mathematical Representation:

Let (,) represent the intensity of a pixel at coordinates (,) in the original image.

Unsharp Masking:

Unsharp Mask=(,)Blurred Image Enhanced Image=(,)+Unsharp Mask

High-Boost Filtering:

High-Boost Filter=(,)Blurred Image Enhanced Image=(,)+High-Boost Filter

where:

  • is a scaling factor that determines the strength of the enhancement.

Implementation in Python:


Here's an example of implementing unsharp masking and high-boost filtering in Python with OpenCV:


```python

import cv2

import numpy as np

import matplotlib.pyplot as plt


# Read the image in grayscale

original_image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)


# Blur the original image using a Gaussian filter

blurred_image = cv2.GaussianBlur(original_image, (5, 5), 0)


# Unsharp Masking

unsharp_mask = original_image - blurred_image

enhanced_image_unsharp = original_image + unsharp_mask


# High-Boost Filtering

k = 1.5

high_boost_filter = original_image - k * blurred_image

enhanced_image_high_boost = original_image + high_boost_filter


# Clip values to ensure they are in the valid intensity range [0, 255]

enhanced_image_unsharp = np.clip(enhanced_image_unsharp, 0, 255).astype(np.uint8)

enhanced_image_high_boost = np.clip(enhanced_image_high_boost, 0, 255).astype(np.uint8)


# Display the original and enhanced images

plt.figure(figsize=(15, 5))

plt.subplot(1, 3, 1), plt.imshow(original_image, cmap='gray'), plt.title('Original Image')

plt.subplot(1, 3, 2), plt.imshow(enhanced_image_unsharp, cmap='gray'), plt.title('Enhanced Image (Unsharp Mask)')

plt.subplot(1, 3, 3), plt.imshow(enhanced_image_high_boost, cmap='gray'), plt.title('Enhanced Image (High-Boost Filter)')

plt.show()

```


In this example, the original image is first blurred using a Gaussian filter. Then, the unsharp mask and high-boost filter are created and added back to the original image. The scaling factor \( k \) can be adjusted to control the strength of the enhancement. Adjust the filter parameters based on your specific requirements.