Contrast Stretching and Range Compression in Python with OpenCV
Contrast Stretching and Range Compression in Python
This script loads a grayscale image and applies two intensity transformations: contrast stretching and range compression. The results are displayed side by side with the original image using Matplotlib.
Loading the Image and Input Parameters
The image Cat.jpg is loaded in grayscale. The user enters two coordinate points (A and B) that define the breakpoints of the piecewise linear transformation, along with the constant c used for range compression.
Helper Functions
Line Equation Function
The function prava(x1, y1, x2, y2) calculates the slope m and intercept b of the line passing through two points.
Contrast Stretching Function
The function konstrast(slika, koordinati) applies a piecewise linear transformation with three segments:
- For pixel values from 0 to a, the first line segment from (0, 0) to point A is used.
- For pixel values from a to b, the second segment from point A to point B is used.
- For pixel values above b, the third segment from point B to (255, 255) is used.
Range Compression Function
The function Range(slika, c) applies the logarithmic transformation s = c * log(1 + r) to each pixel, which compresses the dynamic range of the image.
Main Program
Both transformations are applied to the original image, and the three resulting images are displayed with titles Originalna slika, Contrast Stretching, and Range compression.
import numpy as np
import cv2
import math as mp
from matplotlib import pyplot as plt
# Vchituvame slika
slika = cv2.imread("Cat.jpg", 0)
# Vnesuvame koordinati i parametar C
k1 = int(input("A: Vnesi koordinat 1: "))
k2 = int(input("A: Vnesi koordinat 2: "))
k3 = int(input("B: Vnesi koordinat 3: "))
k4 = int(input("B: Vnesi koordinat 4: "))
koordinati = [(k1, k2), (k3, k4)]
c = int(input("Vnesi vrednost za c: "))
# Definirame funkcii
def prava(x1, y1, x2, y2):
m = (y2 - y1) / (x2 - x1)
b = y1 - m * x1
return m, b
def konstrast(slika, koordinati):
tochka_A = koordinati[0] # toa e (50,30)
tochka_B = koordinati[1] # toa e (150,200)
a = tochka_A[0] # toa e 50
yA = tochka_A[1] # toa e 30
b = tochka_B[0] # toa e 150
yB = tochka_B[1] # toa e 200
alfa, presekA = prava(0, 0, a, yA)
beta, presekB = prava(a, yA, b, yB)
gama, presekG = prava(b, yB, 255, 255)
praznaSlika = np.zeros((slika.shape[0], slika.shape[1]), np.uint8)
#cv2.imshow("Test", praznaSlika)
for i in range(slika.shape[0]):
for j in range(slika.shape[1]):
x = slika[i, j]
if 0 <= x < a:
y = alfa * x + presekA
praznaSlika[i, j] = y
elif a <= x < b:
y = beta * x + presekB
praznaSlika[i, j] = y
else:
y = gama * x + presekG
praznaSlika[i, j] = y
return praznaSlika
def Range(slika, c):
praznaSlika = np.zeros((slika.shape[0], slika.shape[1]), np.uint8)
for i in range(slika.shape[0]):
for j in range(slika.shape[1]):
x = slika[i, j]
praznaSlika[i, j] = c * mp.log(1 + x, 10)
return praznaSlika
# Dobivanje na novite sliki so primena na Contrast stretching i Range compression algoritam
slikaContrast = konstrast(slika, koordinati)
slikaRange = Range(slika, c)
plt.subplot(131), plt.imshow(slika, 'gray'), plt.title("Originalna slika")
plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis
plt.subplot(132), plt.imshow(slikaContrast, 'gray'), plt.title("Contrast Stretching")
plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis
plt.subplot(133), plt.imshow(slikaRange, 'gray'), plt.title("Range compression")
plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()