Project

General

Profile

Codes » History » Version 5

Anonymous, 01/12/2022 06:04 PM

1 1 Anonymous
h1. Codes
2 4 Anonymous
3 5 Anonymous
h2. MainDisplay.py : To calculate blended image 
4 4 Anonymous
5 3 Anonymous
<pre><code class="python">
6 4 Anonymous
import cv2 as cv
7
from CalculateDisplayImage import CalculateDisplayImage
8
9
CDI = CalculateDisplayImage()
10
11
##
12
# @brief
13
#
14
# This class displays blended images.
15
# This class is made by Vaibhav, Doxygened by Xu Minghao.
16
#
17
18
19
class MainDisplay(object):
20
21
    ##
22
    # @brief
23
    # Display the blended images.
24
    # @param img is the image blended with masks.
25
    def display(img):
26
        cv.imshow('img', img)
27
        cv.waitKey(0)
28
        cv.destroyAllWindows()
29
30
    # The constructor.
31
    def __init__(self):
32
        pass
33
34
    ## A class variable.
35
    # To store the blended images.
36
    res = CDI.getDisplayImage(CDI.calculate())
37
38
    display(res[0])
39
    # display(res[1])
40
41
</code></pre>
42
43
44 5 Anonymous
h2. CalculateDisplayImage.py : To calculate blended image 
45 4 Anonymous
46
<pre><code class="python">
47
import cv2 as cv
48
import numpy as np
49
from ConfigureReader import ConfigureReader
50
from ImageReader import ImageReader
51
52
CR = ConfigureReader()
53
IR = ImageReader()
54
55
##
56
# @brief
57
#
58
# This class calculates blended image.
59
# This class is made by Minghao, Shiva, Son, and Vaibhav, Doxygened by Rikuto Momoi.
60
#
61
62
63
class CalculateDisplayImage(object):
64
65
    # The constructor
66
    def __init__(self):
67
        projector_image_width = CR.getProjectorImageWidth()
68
        projector_distance = CR.getProjectorDistance()
69
        self.image_width = CR.getImageWidth()
70
        self.image_height = CR.getImageHeight()
71
        self.gamma = CR.getGamma()
72
        self.method = CR.getMethod()
73
        self.np_left = IR.getImage()[0]
74
        self.np_right = IR.getImage()[1]
75
        self.overlap_pixels = round(
76
            self.image_width*(projector_image_width - projector_distance)/projector_image_width)
77
78
    ##
79
    # @brief
80
    # Get the blended image.
81
    # @param corrected_tuple contains the gamma corrected image left and right.
82
    # @return RGB formatted blended images.
83
    def getDisplayImage(self, corrected_tuple):
84
        corrected_left, corrected_right = corrected_tuple
85
        # to RGB
86
        blended_left = np.rint(corrected_left*255).astype(np.uint8)
87
        blended_right = np.rint(corrected_right*255).astype(np.uint8)
88
        # save images
89
        cv.imwrite('src/blended_left.jpg', blended_left)
90
        cv.imwrite('src/blended_right.jpg', blended_right)
91
        return blended_left, blended_right
92
93
    ##
94
    # @brief
95
    # Control the texture of the mask.
96
    # @param distance is the distance from the start point of the target overlap region.
97
    # @param monotonicity is the monotonicity of the intensity function.
98
    # @return Intensity control value.
99
    def intensityController(self, distance, monotonicity):
100
101
        if monotonicity == 'linearly_increase':
102
            return -distance/self.overlap_pixels + 1
103
        elif monotonicity == 'linearly_decrease':
104
            return distance/self.overlap_pixels
105
        elif monotonicity == 'nonlinearly_increase':
106
            return -np.power(distance/self.overlap_pixels, 2) + 1
107
        elif monotonicity == 'nonlinearly_decrease':
108
            return np.power(distance/self.overlap_pixels, 2)
109
110
    ##
111
    # @brief
112
    # Generates masks.
113
    # @param direction is the direction of the mask.
114
    # @return Gradient masks (in linear case).
115
    def maskGenerator(self, direction):
116
        
117
        # assume images have the same size
118
        mask = np.ones(self.np_left.shape)
119
        for columns in range(self.image_width-self.overlap_pixels-1, self.image_width):
120
            mask[0, columns, :] *= self.intensityController(
121
                columns-(self.image_width-self.overlap_pixels-1), monotonicity=self.method+'ly_increase')
122
        # replacement is more efficient than multiplication
123
        for rows in range(1, self.image_height):
124
            mask[rows, :, :] = mask[0, :, :]
125
126
        if direction == 'left':
127
            return mask
128
        elif direction == 'right':
129
            # flip direction of mask to right
130
            return np.flip(mask, axis=1)
131
132
    ##
133
    # @brief
134
    # Get gamma corrected image.
135
    # @param img is the image blended with masks.
136
    # @param direction is the direction of the image.
137
    # @param gamma is the gamma value.
138
    # @return Gamma corrected numpy array.
139
    def gammaCorrection(self, img, direction, gamma):
140
141
        if direction == 'left':
142
            for rows in range(self.image_height):
143
                for columns in range(self.image_width-self.overlap_pixels-1, self.image_width):
144
                    img[rows][columns][:] *= np.power(self.intensityController(
145
                        columns-(self.image_width-self.overlap_pixels-1), monotonicity=self.method + 'ly_increase'), gamma)
146
            return img
147
148
        elif direction == 'right':
149
            for rows in range(self.image_height):
150
                for columns in range(self.overlap_pixels-1):
151
                    img[rows][columns][:] *= np.power(
152
                        self.intensityController(columns, monotonicity=self.method + 'ly_decrease'), gamma)
153
            return img
154
155
    ##
156
    # @brief
157
    # Calculate the image to display.
158
    # @return final blended image left and right.
159
    def calculate(self):
160
        # generate masks
161
        mask_left = self.maskGenerator(
162
            direction='left')
163
        mask_right = self.maskGenerator(
164
            direction='right')
165
        # blend images with masks
166
        with_mask_left = np.multiply(self.np_left, mask_left)
167
        with_mask_right = np.multiply(self.np_right, mask_right)
168
        # apply gamma correction
169
        corrected_left = self.gammaCorrection(
170
            with_mask_left, direction='left', gamma=self.gamma)
171
        corrected_right = self.gammaCorrection(
172
            with_mask_right, direction='right', gamma=self.gamma)
173
        return corrected_left, corrected_right
174
175
    ## @var gamma
176
    # Gamma value.
177
    ## @var method
178
    # Method of intensity control.
179
    ## @var np_left
180
    # Normalized Numpy array of left image.
181
    ## @var np_right
182
    # Normalized Numpy array of right image.
183
    ## @var overlap_pixels
184
    # Overlap region width.
185
    ## @var image_height
186
    # Image height.
187
    ## @var image_width
188
    # Image width.
189
190
</code></pre>
191
192 5 Anonymous
h2. ConfigureReader : Initialize the values to process the edge-blending
193 4 Anonymous
194
<pre><code class="python">
195
from configparser import ConfigParser
196
197
##
198
# @brief
199
#
200
# This class reads initial values that will be needed to process the edge-blending.
201
# This class is made by Son and Minghao, Doxygened by Konatsu.
202
#
203
204
205
class ConfigureReader(object):
206
207
    # The constructor.
208
    def __init__(self):
209
        self.config = ConfigParser()
210
        self.config.read('config.ini')
211
212
    ##
213
    # @brief
214
    # Get split image height.
215
    # @return image height in int.
216
    def getImageWidth(self):
217
        return int(self.config['DEFAULT']['ImageWidth'])
218
219
    ##
220
    # @brief
221
    # Get split image width.
222
    # @return image width in int.
223
    def getImageHeight(self):
224
        return int(self.config['DEFAULT']['ImageHeight'])
225
226
    ##
227
    # @brief
228
    # Get distance between two projectors.
229
    # @return projector distance in float.
230
    def getProjectorDistance(self):
231
        return float(self.config['DEFAULT']['projector_distance'])
232
233
    ##
234
    # @brief
235
    # Get projected image width.
236
    # @return image width in float.
237
    def getProjectorImageWidth(self):
238
        return float(self.config['DEFAULT']['projector_image_width'])
239
240
    ##
241
    # @brief
242
    # Get gamma value.
243
    # @return gamma value in float.
244
    def getGamma(self):
245
        return float(self.config['DEFAULT']['gamma'])
246
247
    ##
248
    # @brief
249
    # Get edge-blending method.
250
    # @return method in string.
251
    def getMethod(self):
252
        return str(self.config['DEFAULT']['method'])
253
254
    ##
255
    # @brief
256
    # Get image path (image should be put inside src).
257
    # @return image path in string.
258
    def getImagePath(self):
259
        return 'src/' + str(self.config['DEFAULT']['ImageNameLeft']), 'src/' + str(self.config['DEFAULT']['ImageNameRight'])
260
261
    # @var config
262
    # The configuration file.
263
264
</code></pre>
265
266 5 Anonymous
h2. ImageReader.py : To read image and normalize them into numpy array tuple.
267 4 Anonymous
268
<pre><code class="python">
269
import cv2 as cv
270
import numpy as np
271
from ConfigureReader import ConfigureReader
272
273
CR = ConfigureReader()
274
275
##
276
# @brief
277
#
278
# This class reads images and normalize them into numpy array tuple.
279
# This class is made by Shiva, Doxygened by Rikuto Momoi
280
#
281
282
283
class ImageReader(object):
284
285
    # The constructer
286
    def __init__(self):
287
        pass
288
289
    ##
290
    # @brief 
291
    # Get image in a normalized numpy array
292
    # @return normalized numpy array
293
    def getImage(self):
294
        return np.array(cv.imread(CR.getImagePath()[0]))/255, np.array(cv.imread(CR.getImagePath()[1]))/255
295 3 Anonymous
296
</code></pre>