Project

General

Profile

Feature #489 » CalculateDisplayImage.py

Anonymous, 01/12/2022 11:04 PM

 
1
import cv2 as cv
2
import numpy as np
3
from ConfigureReader import ConfigureReader
4
from ImageReader import ImageReader
5

    
6
CR = ConfigureReader()
7
IR = ImageReader()
8

    
9
##
10
# @brief
11
#
12
# This class calculates blended image.
13
# This class is made by Minghao, Shiva, Son, and Vaibhav, Doxygened by Rikuto Momoi
14
#
15

    
16

    
17
class CalculateDisplayImage(object):
18

    
19
    # The constructor
20
    def __init__(self):
21
        projector_image_width = CR.getProjectorImageWidth()
22
        projector_distance = CR.getProjectorDistance()
23
        self.gamma = CR.getGamma()
24
        self.method = CR.getMethod()
25
        self.np_left = IR.getImage()[0]
26
        self.np_right = IR.getImage()[1]
27
        self.overlap_pixels = round(
28
            self.np_left.shape[1]*(projector_image_width - projector_distance)/projector_image_width)
29

    
30
    ##
31
    # @brief
32
    # Get the blended image
33
    # @param corrected_tuple contains the gamma corrected image left and right
34
    # @return RGB formatted blended images
35
    def getDisplayImage(self, corrected_tuple):
36
        corrected_left, corrected_right = corrected_tuple
37
        # to RGB
38
        blended_left = np.rint(corrected_left*255).astype(np.uint8)
39
        blended_right = np.rint(corrected_right*255).astype(np.uint8)
40
        # save images
41
        cv.imwrite('src/blended_left.jpg', blended_left)
42
        cv.imwrite('src/blended_right.jpg', blended_right)
43
        return blended_left, blended_right
44

    
45
    ##
46
    # @brief 
47
    # Control the texture of the mask
48
    # @param distance is the distance from the start point of the target overlap region
49
    # @param monotonicity is the monotonicity of the intensity function
50
    # @return Intensity control value
51
    def intensityController(self, distance, monotonicity):
52

    
53
        if monotonicity == 'linearly_increase':
54
            return -distance/self.overlap_pixels + 1
55
        elif monotonicity == 'linearly_decrease':
56
            return distance/self.overlap_pixels
57
        elif monotonicity == 'nonlinearly_increase':
58
            return -np.power(distance/self.overlap_pixels, 2) + 1
59
        elif monotonicity == 'nonlinearly_decrease':
60
            return np.power(distance/self.overlap_pixels, 2)
61

    
62
    ##
63
    # @brief  
64
    # Generates masks
65
    # @param mask is a white mask with the same size of the image
66
    # @param direction is the direction of the mask
67
    # @return gradient masks (in linear case)
68
    def maskGenerator(self, mask, direction):
69

    
70
        for columns in range(mask.shape[1]-self.overlap_pixels-1, mask.shape[1]):
71
            mask[0, columns, :] *= self.intensityController(
72
                columns-(mask.shape[1]-self.overlap_pixels-1), monotonicity=self.method+'ly_increase')
73
        # replacement is more efficient than multiplication
74
        for rows in range(1, mask.shape[0]):
75
            mask[rows, :, :] = mask[0, :, :]
76

    
77
        if direction == 'left':
78
            return mask
79
        elif direction == 'right':
80
            # flip direction of mask to right
81
            return np.flip(mask, axis=1)
82

    
83
    ##
84
    # @brief
85
    # Get gamma corrected image
86
    # @param img is the image blended with masks
87
    # @param direction is the direction of the image
88
    # @param gamma is the gamma value
89
    # @return gamma corrected numpy array
90
    def gammaCorrection(self, img, direction, gamma):
91

    
92
        if direction == 'left':
93
            for rows in range(img.shape[0]):
94
                for columns in range(img.shape[1]-self.overlap_pixels-1, img.shape[1]):
95
                    img[rows][columns][:] *= np.power(self.intensityController(
96
                        columns-(img.shape[1]-self.overlap_pixels-1), monotonicity=self.method + 'ly_increase'), gamma)
97
            return img
98

    
99
        elif direction == 'right':
100
            for rows in range(img.shape[0]):
101
                for columns in range(self.overlap_pixels-1):
102
                    img[rows][columns][:] *= np.power(
103
                        self.intensityController(columns, monotonicity=self.method + 'ly_decrease'), gamma)
104
            return img
105

    
106
    ##
107
    # @brief  
108
    # Calculate the image to display
109
    # @return final blended image left and right
110
    def calculate(self):
111
        # generate masks
112
        mask_left = self.maskGenerator(
113
            np.ones(self.np_left.shape), direction='left')
114
        mask_right = self.maskGenerator(
115
            np.ones(self.np_right.shape), direction='right')
116
        # blend images with masks
117
        with_mask_left = np.multiply(self.np_left, mask_left)
118
        with_mask_right = np.multiply(self.np_right, mask_right)
119
        # apply gamma correction
120
        corrected_left = self.gammaCorrection(
121
            with_mask_left, direction='left', gamma=self.gamma)
122
        corrected_right = self.gammaCorrection(
123
            with_mask_right, direction='right', gamma=self.gamma)
124
        return corrected_left, corrected_right
(2-2/2)