Project

General

Profile

Codes » History » Version 30

Mitsuki EIKI, 01/16/2025 02:13 PM

1 1 Mitsuki EIKI
h1. Codes
2 2 Mitsuki EIKI
3 3 Man Mong CHAN
[[Wiki]] | [[About_Us]] | [[Project_Overview]] | [[UML_Diagram]] | [[Codes]]
4 4 Kentaro HARATAKE
5 26 Mitsuki EIKI
h1. Config Class Code
6 6 Mitsuki EIKI
7 30 Mitsuki EIKI
<pre><code class="python">
8
#!/usr/bin/env python
9
# -*- coding: utf-8 -*-
10
from config import Config
11
from img_processor import ImgProcessor
12
from display_img import DisplayImg
13
import cv2
14
15
class MainStitcher:
16
    """!
17
    @brief A class responsible for stitching and displaying images in a projection system.
18
19
    The class integrates configuration settings from the `Config` class and display properties
20
    from the `DisplayImg` class to handle the main stitching and display logic.
21
    """
22
23
    def __init__(self, dImg):
24
        """!
25
        @brief Initializes the MainStitcher with configuration and display image settings.
26
        @param config An instance of the Config class containing projection configuration.
27
        @param dImg An instance of the DisplayImg class containing display settings.
28
        """
29
        self.__displayImg = dImg
30
31
32
    #for single monitor/mirroring
33
    def singleDisplay(self):
34
        """!
35
        @brief use two laptops to project the final processed images.
36
        """
37
        img = self.__displayImg.getImg()
38
        side = self.__displayImg.getSide()
39
40
        # cv2.namedWindow(side, cv2.WINDOW_NORMAL)
41
        cv2.imshow(side, img)
42
        # cv2.setWindowProperty(side, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
43
44
45
    #for double extended monitor
46
    def doubleDisplay(self, monitorWidth):
47
        """!
48
        @brief use two laptops to project the final processed images.
49
        """
50
        img = self.__displayImg.getImg()
51
        side = self.__displayImg.getSide()
52
53
        """
54
        In moveWindow(name, x, y), we can replace x with the window size or something
55
        """
56
        if(side == "Left"):
57
            cv2.namedWindow(side, cv2.WINDOW_NORMAL)
58
            cv2.moveWindow(side, 0, 0)
59
            cv2.imshow(side, img)
60
            cv2.resizeWindow(side, monitorWidth, 1080)
61
            cv2.setWindowProperty(side, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
62
63
        elif(side == "Right"):
64
            cv2.namedWindow(side, cv2.WINDOW_NORMAL)
65
            cv2.moveWindow(side, monitorWidth, 0)
66
            cv2.imshow(side, img)
67
            cv2.resizeWindow(side, monitorWidth, 1080)
68
            cv2.setWindowProperty(side, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
69
70
    def save(self):
71
        cv2.imwrite("./img/processed/" + self.__displayImg.getSide() + "_img.png", self.__displayImg.getImg())
72
73
74
def main():
75
    config = Config.readConfigFile()
76
77
    imgProcessor = ImgProcessor(config)
78
79
    l_img, r_img = imgProcessor.cropImage()
80
    l_alpha_processed, r_alpha_processed = imgProcessor.alphaBlend(l_img, r_img)
81
82
83
    l_alpha_gamma_processed = imgProcessor.GammaCorrection(l_alpha_processed)
84
    r_alpha_gamma_processed = imgProcessor.GammaCorrection(r_alpha_processed)
85
86
    l_displayImg = DisplayImg(l_alpha_gamma_processed.shape[1] ,l_alpha_gamma_processed.shape[0], config.getOverlapWidth(), l_alpha_gamma_processed, "Left")
87
    r_displayImg = DisplayImg(r_alpha_gamma_processed.shape[1] ,r_alpha_gamma_processed.shape[0], config.getOverlapWidth(), r_alpha_gamma_processed, "Right")
88
89
    l_stitcher = MainStitcher(l_displayImg)
90
    r_stitcher = MainStitcher(r_displayImg)
91
92
93
    print(config.getIsDualMonitor())
94
95
    if config.getIsDualMonitor():
96
        l_stitcher.doubleDisplay(config.getMonitorWidth())
97
        r_stitcher.doubleDisplay(config.getMonitorWidth())
98
    else:
99
        if config.getSide().lower() == "right":
100
            r_stitcher.singleDisplay()
101
        else:
102
            l_stitcher.singleDisplay()
103
104
    cv2.waitKey(0)
105
    cv2.destroyAllWindows()
106
107
108
    l_stitcher.save()
109
    r_stitcher.save()
110
111
if __name__ == "__main__":
112
    main()
113
</code></pre>
114
115 26 Mitsuki EIKI
h2. config.py: Configuration Class
116
117 29 Mitsuki EIKI
<pre><code class="python">
118 5 Mitsuki EIKI
#!/usr/bin/env python
119 1 Mitsuki EIKI
# -*- coding: utf-8 -*-
120
from distutils.util import strtobool
121 26 Mitsuki EIKI
122 1 Mitsuki EIKI
class Config(object):
123 26 Mitsuki EIKI
    def __init__(self, pnd, prd, w, h, p, gamma, overlapWidth, side, isDual, monitorWidth):
124 1 Mitsuki EIKI
        """!
125
        Constructor for Config class.
126 8 Mitsuki EIKI
127
        @param pnd: Projection distance.
128
        @param prd: Projector distance.
129
        @param w: Image width.
130
        @param h: Image height.
131
        @param p: Path to the image.
132
        @param gamma: Gamma value for adjustments.
133 1 Mitsuki EIKI
        @param overlapWidth: Width of the overlap area.
134
        @param side: Side of projection.
135 24 Mitsuki EIKI
        """
136 1 Mitsuki EIKI
        self.__projection_distance = pnd
137
        self.__projector_diatance = prd
138
        self.__img_width = w
139 8 Mitsuki EIKI
        self.__img_height = h
140
        self.__img_path = p
141 1 Mitsuki EIKI
        self.__gamma = gamma
142 8 Mitsuki EIKI
        self.__overlapWidth = overlapWidth
143 24 Mitsuki EIKI
        self.__side = side
144 25 Mitsuki EIKI
        self.__isDualMonitor = isDual
145 8 Mitsuki EIKI
        self.__monitorWidth = monitorWidth
146
147 7 Mitsuki EIKI
    def getProjectionDistance(self):
148 5 Mitsuki EIKI
        """!
149
        Retrieve the projection distance.
150 8 Mitsuki EIKI
151
        @return: Projection distance as an integer.
152 5 Mitsuki EIKI
        """
153
        return int(self.__projection_distance)
154 1 Mitsuki EIKI
155
    def getProjectorDistance(self):
156
        """!
157 5 Mitsuki EIKI
        Retrieve the projector distance.
158 8 Mitsuki EIKI
159
        @return: Projector distance as an integer.
160 1 Mitsuki EIKI
        """
161
        return int(self.__projector_diatance)
162
163 8 Mitsuki EIKI
    def getImgWidth(self):
164
        """!
165
        Retrieve the image width.
166 1 Mitsuki EIKI
167 8 Mitsuki EIKI
        @return: Image width as an integer.
168
        """
169
        return int(self.__img_width)
170
171
    def getImgHeight(self):
172
        """!
173
        Retrieve the image height.
174
175
        @return: Image height as an integer.
176
        """
177
        return int(self.__img_height)
178
179
    def getImgPath(self):
180
        """!
181
        Retrieve the image path.
182
183
        @return: Image path as a string.
184
        """
185
        return str(self.__img_path)
186
187
    def getGamma(self):
188
        """!
189
        Retrieve the gamma value.
190
191
        @return: Gamma value as a float.
192
        """
193
        return float(self.__gamma)
194
195
    def getOverlapWidth(self):
196
        """!
197
        Retrieve the overlap width.
198
199
        @return: Overlap width as an integer.
200
        """
201
        return int(self.__overlapWidth)
202
203
    def getSide(self):
204 1 Mitsuki EIKI
        """!
205 8 Mitsuki EIKI
        Retrieve the side of projection.
206
207 1 Mitsuki EIKI
        @return: Side as a string.
208 8 Mitsuki EIKI
        """
209
        return str(self.__side)
210 24 Mitsuki EIKI
    
211 8 Mitsuki EIKI
    def getIsDualMonitor(self):
212
        return bool(strtobool(self.__isDualMonitor))
213
214
    def getMonitorWidth(self):
215
        return int(self.__monitorWidth)
216
217 1 Mitsuki EIKI
    @staticmethod
218
    def readConfigFile():
219
        """!
220
        Reads the configuration from a config.ini file and returns a Config object.
221 8 Mitsuki EIKI
222
        @return: Config object with settings loaded from config.ini.
223 1 Mitsuki EIKI
        """
224
        import configparser
225 8 Mitsuki EIKI
        config = configparser.ConfigParser()
226
        config.read('config.ini')
227
228
        __img_path = config["settings"]["imagePath"]
229
        __img_width = config["settings"]["imageWidth"]
230
        __img_height = config["settings"]["imageHeight"]
231 1 Mitsuki EIKI
        __projection_distance = config["settings"]["projectionDistance"]
232
        __projector_diatance = config["settings"]["projectorDistance"]
233
        __gamma = config["settings"]["gamma"]
234 8 Mitsuki EIKI
        __overlapWidth = config["settings"]["overlapWidth"]
235 1 Mitsuki EIKI
        __side = config["settings"]["side"]
236
        __isDualMonitor = config["settings"]["isDualMonitor"]
237 26 Mitsuki EIKI
        __monitorWidth = config["settings"]["monitorWidth"]
238 1 Mitsuki EIKI
        
239 26 Mitsuki EIKI
        return Config(__projection_distance, __projector_diatance, __img_width, __img_height, __img_path, __gamma, __overlapWidth, __side, __isDualMonitor, __monitorWidth)
240 29 Mitsuki EIKI
</code></pre>
241 30 Mitsuki EIKI
242
h2. config.py: Configuration Class