contrasts.py 4.69 KB
Newer Older
1
import numpy as np
2
import math
3
import cv2 as cv
4
from skimage import color
5

6
7
# TODO create generic class

8

9
10
11
12
class Contrast(object):
    """Base class for color contrasts"""
    def __init__(self, img):
        self._img = img
13

14

15
16
class Monochromatic(Contrast):
    """docstring for Monochromatic"""
17
    def __init__(self, img, method='luminance'):
18
        super(Monochromatic, self).__init__(img)
19

20
        meth = getattr(Monochromatic, method)
21
        self.ctrst = meth(self)
22

23
24
    def luminance(self):
        """Creates light/dark values using luminance quantifiers for RGB
25

26
27
           The array has the same dimensions as the image. However the third
           does only have the size 1 which contains the luminance value
28
        """
29
30
        # Luminance Faktoren nach
        # http://introcs.cs.princeton.edu/python/31datatype/luminance.py.html
31
        luminance_factors = np.array([.114, .587, .299])
32

33
34
        # Erzeugung eines eindimensionalen Arrays für die effizientere
        # Berechnung
35
        self._img = np.multiply(self._img, luminance_factors)
36

37
38
        # addiert alle Werte auf einer bestimmten Achse
        luminances = np.sum(self._img, axis=2)
39
        luminances = luminances.astype(np.uint8, copy=True)
40

41
        return luminances
42

43
44
45
46
    def value(self):
        """Creates light/dark values using the value channel in HSV"""
        img = cv.cvtColor(self._img, cv.COLOR_BGR2HSV)
        values = img[:, :, 2].copy()
47

48
        return values
49

50
51
52
53
    def lightness(self):
        """Creates light/dark values using the value channel in HSV"""
        img = cv.cvtColor(self._img, cv.COLOR_BGR2HLS)
        lightness = img[:, :, 1].copy()
54

55
        return lightness
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    def redniss_lab(self):
        """Returns the redness contrast on the basis of CIE Lab

           The a channel of the representation the image in CIE Lab is
           isolated and the value 127 set as 0 to eliminate the green
           shares of a.
        """
        img = cv.cvtColor(self._img, cv.COLOR_BGR2Lab)
        lab_a = img[:, :, 1].copy()

        lab_a[lab_a < 128] = 0
        redness = np.subtract(lab_a[lab_a > 127], 128)

        return redness

    def colf_val_point(self):
        """calculates the most colourful value point in an image
74

75
76
77
78
79
80
        used to identify tinting or toning images with its specific colourful
        areas in very light or darker value regions
        """

        # as long as opencv is used, convert RGB to RGB
        imgrgb = self._img[:, :, ::-1]
81
82
        assert(np.array_equal(self._img,
               imgrgb[:, :, ::-1])), "opencv scikit-image conversion wrong"
83
84
85
86
87
88
        imglab = color.rgb2lab(imgrgb)
        imglch = color.lab2lch(imglab)

        value = Monochromatic(self._img, method='value')
        value = value.value()

89
        imgcv = imglch[:, :, 1].astype(np.uint8)
90
91
        imgcv = np.dstack((imgcv, value))

92
93
        perc90 = np.percentile(imgcv[:, :, 0], 90)
        indices_colful = np.where(imgcv[:, :, 0] > perc90)
94
95
96
97
        colful_values = imgcv[indices_colful][:, 1]
        colful_value_max = np.median(colful_values)

        return np.array([[[colful_value_max]]])
98

99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

class Saturation(Contrast):
    """docstring for Saturation"""
    def __init__(self, img, method='saturation'):
        super(Saturation, self).__init__(img)

        meth = getattr(Saturation, method)
        self.ctrst = meth(self)

    def saturation(self):
        """docstring for saturation"""
        img = cv.cvtColor(self._img, cv.COLOR_BGR2HSV)
        saturations = img[:, :, 1].copy()

        return saturations

115
116
    # CTRL stimmt vom Ergebnis noch nicht, liegt es am Rückgabedatentyp Float?
    def colourfulness(self):
117
        """docstring for chroma"""
118
119
120

        imglab = color.rgb2lab(self._img)
        imglch = color.lab2lch(imglab)
121

122
123
124
125
126
127
        # TODO geht garnicht, weil nicht angemessen gerundet wird
        # und skimage auch davor warnt
        imglch = imglch.astype(np.uint16)
        colourfulness = imglch[:, :, 1]

        return colourfulness
128
129
130
131


class Hue(Contrast):
    """docstring for Saturation"""
132
    def __init__(self, img, method='hsV'):
133
134
135
136
137
        super(Hue, self).__init__(img)

        meth = getattr(Hue, method)
        self.ctrst = meth(self)

138
139
140
    def hsV(self):
        """calculates the Hue value by using the HSV colorspace"""

141
142
143
        img = cv.cvtColor(self._img, cv.COLOR_BGR2HSV)
        hues = img[:, :, 0].copy()

144
145
        print('hsv')

146
147
        return hues

148
149
150
    def labHcl(self) -> np.uint16:
        """calculates the Hue value by using the CIE LabHCL colorspace"""

151
        imglab = color.rgb2lab(self._img[:, :, ::-1])
152
153
154
155
156
157
158
159
160
        imglch = color.lab2lch(imglab)
        hues = imglch[:, :, 2]

        vdegrees = np.vectorize(math.degrees)
        hues = vdegrees(hues)

        hues = np.around(hues).astype(np.uint16)

        return hues