Project

General

Profile

Files » x_curve.py

KAUNG Zin Thu, 01/05/2026 02:50 PM

 
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3

    
4
##
5
# @file blending_mechanics_visualization.py
6
# @brief Visualizes spatial alpha blending mechanics with and without gamma correction.
7
#
8
# @details
9
# This program generates a detailed visualization of projector edge blending
10
# in an overlap region. It compares:
11
# - Linear alpha blending (baseline / incorrect approach)
12
# - Gamma-corrected alpha blending (final solution)
13
#
14
# The graph highlights how gamma correction compensates for nonlinear
15
# projector luminance response, preventing visible dark seams
16
# in the overlap region.
17
#
18
# The output image is designed for inclusion in technical documentation
19
# or a project wiki to explain blending mechanics visually.
20

    
21
import numpy as np
22
import matplotlib.pyplot as plt
23

    
24

    
25
##
26
# @brief Plots spatial alpha blending behavior in an overlap region.
27
#
28
# @details
29
# This function simulates the intensity distribution of two overlapping
30
# projectors across a horizontal overlap zone.
31
#
32
# Two blending strategies are visualized:
33
# 1. Linear alpha blending (y = x)
34
# 2. Gamma-corrected alpha blending (y = x^(1/gamma))
35
#
36
# The resulting plot illustrates how gamma correction increases effective
37
# light energy in the overlap region, correcting the dark band artifact
38
# caused by naive linear blending.
39
#
40
# The shaded regions emphasize the difference in projected light energy
41
# between linear and gamma-corrected approaches.
42
#
43
# @note
44
# This visualization is analytical and explanatory in nature.
45
# It does not represent raw pixel blending, but projected luminance behavior.
46
#
47
# @return None
48
def plot_blending_mechanics_unique():
49
    ##
50
    # @brief Define overlap region configuration.
51
    #
52
    # @details
53
    # overlap_pixels represents the horizontal width (in pixels)
54
    # where two projectors overlap.
55
    overlap_pixels = 256  # Example: Change this to your actual overlap width
56

    
57
    ##
58
    # @brief Generate pixel coordinate ranges.
59
    #
60
    # @details
61
    # x_pixels is used for spatial positioning,
62
    # while x_normalized maps the same region into [0, 1]
63
    # for alpha calculations.
64
    x_pixels = np.linspace(0, overlap_pixels, 500)
65
    x_normalized = np.linspace(0, 1, 500)
66

    
67
    ##
68
    # @brief Compute linear alpha blending weights (baseline).
69
    #
70
    # @details
71
    # These represent a naive linear fade-out / fade-in
72
    # without accounting for projector gamma characteristics.
73
    alpha_left_lin = 1.0 - x_normalized
74
    alpha_right_lin = x_normalized
75

    
76
    ##
77
    # @brief Compute gamma-corrected alpha blending weights.
78
    #
79
    # @details
80
    # Gamma correction compensates for nonlinear luminance response
81
    # of projectors.
82
    #
83
    # Formula:
84
    # @f[
85
    #   \alpha_{corrected} = \alpha^{(1/\gamma)}
86
    # @f]
87
    gamma = 2.2  # Projector gamma value
88
    alpha_left_corr = np.power(alpha_left_lin, 1.0 / gamma)
89
    alpha_right_corr = np.power(alpha_right_lin, 1.0 / gamma)
90

    
91
    ##
92
    # @brief Initialize plotting canvas.
93
    plt.figure(figsize=(10, 6))
94

    
95
    ##
96
    # @brief Plot gamma-corrected projector outputs.
97
    #
98
    # @details
99
    # These curves represent the final projected light intensities
100
    # after gamma compensation.
101
    plt.plot(x_pixels, alpha_left_corr, 'b-', linewidth=3, label='Left Projector Output')
102
    plt.plot(x_pixels, alpha_right_corr, 'r-', linewidth=3, label='Right Projector Output')
103

    
104
    ##
105
    # @brief Plot linear blending reference curves.
106
    #
107
    # @details
108
    # Dashed lines illustrate the baseline case where no gamma
109
    # correction is applied.
110
    plt.plot(x_pixels, alpha_left_lin, 'k:', linewidth=1.5, alpha=0.5,
111
             label='Linear Reference (No Correction)')
112
    plt.plot(x_pixels, alpha_right_lin, 'k:', linewidth=1.5, alpha=0.5)
113

    
114
    ##
115
    # @brief Visualize additional light energy introduced by gamma correction.
116
    #
117
    # @details
118
    # The shaded regions represent the difference between
119
    # linear and gamma-corrected intensity distributions,
120
    # emphasizing how gamma correction boosts luminance
121
    # in the overlap region.
122
    plt.fill_between(x_pixels, alpha_left_corr, alpha_left_lin,
123
                     color='blue', alpha=0.1)
124
    plt.fill_between(x_pixels, alpha_right_corr, alpha_right_lin,
125
                     color='red', alpha=0.1)
126

    
127
    ##
128
    # @brief Annotate gamma compensation effect.
129
    #
130
    # @details
131
    # Highlights the central region where gamma correction
132
    # mitigates the dark band artifact.
133
    plt.text(overlap_pixels / 2, 0.8,
134
             'Gamma Boost Region\n(Corrects Dark Band)',
135
             horizontalalignment='center',
136
             fontsize=10,
137
             bbox=dict(facecolor='white', alpha=0.8, edgecolor='none'))
138

    
139
    ##
140
    # @brief Configure graph labels and appearance.
141
    plt.title(f'Spatial Intensity Distribution (Overlap: {overlap_pixels}px)',
142
              fontsize=14, fontweight='bold')
143
    plt.xlabel('Pixel Position in Overlap Zone', fontsize=12)
144
    plt.ylabel('Projected Light Intensity (0.0 - 1.0)', fontsize=12)
145
    plt.legend()
146
    plt.grid(True, alpha=0.3)
147

    
148
    ##
149
    # @brief Save visualization to file.
150
    #
151
    # @details
152
    # The generated image is saved as a PNG file for
153
    # easy embedding into documentation or wiki pages.
154
    plt.savefig('custom_blending_curve.png', dpi=100)
155
    print("Saved: custom_blending_curve.png")
156

    
157

    
158
##
159
# @brief Program entry point.
160
#
161
# @details
162
# Executes the blending mechanics visualization when the script
163
# is run directly.
164
if __name__ == "__main__":
165
    plot_blending_mechanics_unique()
(7-7/10)