207 lines
5.2 KiB
Python
Executable File
207 lines
5.2 KiB
Python
Executable File
import cv2
|
|
import numpy as np
|
|
import Utilities
|
|
import math
|
|
|
|
MAX_LUM_VALUES = 256
|
|
|
|
# Task 1
|
|
# function to stretch an image
|
|
def stretchHistogram(img):
|
|
result = img.copy()
|
|
|
|
grayscale = getLuminance(img)
|
|
hist = calculateHistogram(grayscale, MAX_LUM_VALUES)
|
|
minPos, maxPos = findMinMaxPos(hist)
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
result[x][y] = (grayscale[x][y] - minPos) / (maxPos - minPos) * 255.0
|
|
|
|
return result
|
|
|
|
|
|
# Task 2
|
|
# function to equalize an image
|
|
def equalizeHistogram(img):
|
|
result = img.copy()
|
|
|
|
grayscale = getLuminance(img)
|
|
hist = calculateHistogram(grayscale, MAX_LUM_VALUES)
|
|
minPos, maxPos = findMinMaxPos(hist)
|
|
|
|
# Precompute integral of histogram from left to right.
|
|
sum = 0
|
|
integral = []
|
|
for i in range(0, hist.shape[0]):
|
|
sum += hist[i]
|
|
integral.append(sum)
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
# Compute histogram value of pixel.
|
|
bin = int(img[x][y][0] / 255.0 * (MAX_LUM_VALUES - 1))
|
|
# Equalize pixel.
|
|
result[x][y] = (255.0 - 1.0) / (img.shape[0] * img.shape[1]) * integral[bin]
|
|
|
|
return result
|
|
|
|
|
|
# Hilfsfunktion
|
|
# function to apply a look-up table onto an image
|
|
def applyLUT(img, LUT):
|
|
result = img.copy()
|
|
|
|
grayscale = getLuminance(img)
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
# Compute histogram value of pixel.
|
|
bin = int(grayscale[x][y][0] / 255.0 * (MAX_LUM_VALUES - 1))
|
|
|
|
result[x][y][0] = LUT[bin]
|
|
result[x][y][1] = LUT[bin]
|
|
result[x][y][2] = LUT[bin]
|
|
|
|
return result
|
|
|
|
|
|
# Hilfsfunktion
|
|
# function to find the minimum an maximum in a histogram
|
|
def findMinMaxPos(histogram):
|
|
minPos = 0
|
|
maxPos = 255
|
|
|
|
for x in range(0, histogram.shape[0]):
|
|
if histogram[x] > 0:
|
|
minPos = x
|
|
break
|
|
|
|
for x in range(histogram.shape[0] - 1, 0):
|
|
if histogram[x] > 0:
|
|
maxPos = x
|
|
break
|
|
|
|
return minPos, maxPos
|
|
|
|
|
|
# Hilfsfunktion
|
|
# function to create a vector containing the histogram
|
|
def calculateHistogram(img, nrBins):
|
|
# create histogram vector
|
|
histogram = np.zeros([nrBins], dtype=int)
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
bin = int(img[x][y][0] / 255.0 * (nrBins - 1))
|
|
histogram[bin] = histogram[bin] + 1
|
|
|
|
return histogram
|
|
|
|
|
|
def luminanceD65(rgb: np.ndarray) -> np.float64:
|
|
"""
|
|
Compute the luminance value of the specified linear RGB values
|
|
according to the D65 white point.
|
|
|
|
@param rgb(np.ndarray): sRGB image
|
|
|
|
@returns The luminance value
|
|
"""
|
|
return np.float64(rgb @ [0.2126, 0.7152, 0.0722])
|
|
|
|
|
|
def getLuminance(img):
|
|
result = img.copy()
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
lum = luminanceD65(img[x][y])
|
|
result[x][y][0] = lum
|
|
result[x][y][1] = lum
|
|
result[x][y][2] = lum
|
|
|
|
return result
|
|
|
|
|
|
def apply_log(img):
|
|
grayscale = getLuminance(img)
|
|
result = img.copy()
|
|
|
|
# Logarithmic scale factor.
|
|
LOG_SCALE_FACTOR = 2.0
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
|
|
# Compute logarithmically scaled D65 luminace
|
|
# and clamp result to be smaller 255.
|
|
lum = min(255,
|
|
math.log(grayscale[x][y][0]/255.0 + 1)
|
|
* 255.0 * LOG_SCALE_FACTOR)
|
|
|
|
result[x][y][0] = lum
|
|
result[x][y][1] = lum
|
|
result[x][y][2] = lum
|
|
|
|
return result
|
|
|
|
|
|
def apply_exp(img):
|
|
grayscale = getLuminance(img)
|
|
result = img.copy()
|
|
|
|
# Logarithmic scale factor.
|
|
EXP_SCALE_FACTOR = 0.5
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
|
|
# Compute logarithmically scaled D65 luminace
|
|
# and clamp result to be smaller 255.
|
|
lum = min(255,
|
|
(math.exp(grayscale[x][y][0]/255.0) - 1)
|
|
* 255.0 * EXP_SCALE_FACTOR)
|
|
|
|
result[x][y][0] = lum
|
|
result[x][y][1] = lum
|
|
result[x][y][2] = lum
|
|
|
|
return result
|
|
|
|
|
|
def apply_inverse(img):
|
|
grayscale = getLuminance(img)
|
|
result = img.copy()
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
|
|
# Compute logarithmically scaled D65 luminace
|
|
# and clamp result to be smaller 255.
|
|
lum = 255.0 - grayscale[x][y][0]
|
|
|
|
result[x][y][0] = lum
|
|
result[x][y][1] = lum
|
|
result[x][y][2] = lum
|
|
|
|
return result
|
|
|
|
|
|
def apply_threshold(img, threshold):
|
|
grayscale = getLuminance(img)
|
|
result = img.copy()
|
|
|
|
for x in range(0, img.shape[0]):
|
|
for y in range(0, img.shape[1]):
|
|
|
|
lum = 0
|
|
if grayscale[x][y][0] >= threshold:
|
|
lum = 255
|
|
|
|
result[x][y][0] = lum
|
|
result[x][y][1] = lum
|
|
result[x][y][2] = lum
|
|
|
|
return result
|