Skip to content

Commit

Permalink
Merge branch 'dev' into feature/ci
Browse files Browse the repository at this point in the history
  • Loading branch information
davisadam10 committed Aug 2, 2024
2 parents 79f4659 + 83c5d3a commit c67444a
Show file tree
Hide file tree
Showing 27 changed files with 571 additions and 198 deletions.
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ For more enquires please contact

[[email protected]](mailto:[email protected])

The full user guide for OpenVPCal can be found below or here as a pdf [UserGuide](https://github.com/Netflix-Skunkworks/OpenVPCal/blob/main/User_Guide_OpenVPCal.pdf).
The full user guide for OpenVPCal can be found below.
## Quick Start - Tutorial Video
A quick start tutorial video can be found below

[![Tutorial Video - Quick Start](https://img.youtube.com/vi/ORrTdUGl0JI/0.jpg)](https://www.youtube.com/watch?v=ORrTdUGl0JI)

# Table of Contents

Expand Down Expand Up @@ -565,19 +569,19 @@ Right clicking offers a context menu which resets the ROI should you make a mist
</td>
</tr>
<tr>
<td colspan="2" ><strong><code>USE EXTERNAL WHITE POINT</code></strong>
<td colspan="2" ><strong><code>USE WHITE POINT OFFSET</code></strong>
</td>
</tr>
<tr>
<td><code>USE EXTERNAL WHITE POINT</code>
<td><code>USE WHITE POINT OFFSET</code>
</td>
<td>If checked, the plate original white point will be converted to the external white point prior to perform the analysis and the calibration
<td>If checked, the plate original white point will be shofted towards the measured white point of the indicated file, prior to perform the analysis and the calibration
</td>
</tr>
<tr>
<td><code>EXTERNAL WHITE POINT FILE</code>
<td><code>WHITE POINT OFFSET SOURCE FILE</code>
</td>
<td>A path to a file with the external white point
<td>A path to a file with the white point offset source
</td>
</tr>
</table>
Expand Down Expand Up @@ -962,7 +966,7 @@ The widget offers a series of tools:
<tr>
<td><code>Apply White Balance Preview</code>
</td>
<td>Applies a preview of the Auto-WB and or External White Balance, if present
<td>Applies a preview of the Auto-WB and or White Balance Offset, if present
</td>
</tr>
<tr>
Expand Down Expand Up @@ -1372,30 +1376,30 @@ In this use case, we ask to perform an auto white-balance in the camera on the f

##### MATCH WALL CALIBRATION: Shiting the calibration to make multiple walls match

When your stage has multiple LED wall types (brands/models) and you want to match them in camera, this workflow allows you to select a “reference wall” that is used as main target for the calibration. By enabling “Match Reference Wall” and selecting from the dropdown menu one of the other walls from the Stage View Bin, OpenVpCal will make sure that the wall you are calibrating will match the Reference one when keeping the camera at the same white balance. The Reference wall can follow any of the other workflows (Simple, Auto-WB and External White), and these shifts will be handed along to the matching wall(s).
When your stage has multiple LED wall types (brands/models) and you want to match them in camera, this workflow allows you to select a “reference wall” that is used as main target for the calibration. By enabling “Match Reference Wall” and selecting from the dropdown menu one of the other walls from the Stage View Bin, OpenVpCal will make sure that the wall you are calibrating will match the Reference one when keeping the camera at the same white balance. The Reference wall can follow any of the other workflows (Simple, Auto-WB and White Point offset), and these shifts will be handed along to the matching wall(s).

<img src="docs/source/images/image7.png" alt="image_tooltip" width="60%" height="50%">



##### EXTERNAL WHITE BALANCE CALIBRATION: Decoupling lenses or shifting to external white points
##### WHITE POINT OFFSET CALIBRATION: Decoupling lenses or shifting to external white points

Like the auto-wb option, this option allows to correct the plate prior to be passed to the analysis.

However, in this case the calibration plate is white balanced towards an external white point, instead of the target white point. There are different use cases for this workflow, but it has mostly been designed to decouple the effect of the lens used to shoot the calibration plate. When enabeling this option, OpenVpCal requires the user to select a frame from which it will calculate the white balance matrix to apply to the calibration patches. When aiming to decouple the effect of the lens, we perform the workflow in these simple steps:
However, in this case the calibration plate is white balanced towards a different white point, instead of the target white point. There are different use cases for this workflow, but it has mostly been designed to decouple the effect of the lens or filters used to shoot the calibration plate. When enabeling this option, OpenVpCal requires the user to select a frame from which it will calculate the white balance matrix to apply to the calibration patches. When aiming to decouple the effect of the lens, we perform the workflow in these simple steps:



1. Shoot the calibration patches as per **<code>SIMPLE CALIBRATION</code></strong> workflow, setting the camera to the LED wall white point. Once finish to shoot, roll back the sequence to the first frame, where the grey square and circle are;
2. Remove the lens from the camera, don’t change anything else;
3. The incoming light from the LED wall to the sensor will be bright without a lens, so change the shutter speed and/or fps of the camera to make sure that the blurred image doesn’t clip. Ideally it should be exposed correctly (using the false color of the camera, should get to the 18% level).
4. Shoot just a second (a single frame is necessary) of the first patch of the calibration sequence only. You don’t need to run the entire sequence.
5. Use one frame of the clip shot without a lens as External White Point File
5. Use one frame of the clip shot without a lens as White Point Offset Source File

<table>
<tr>
<td colspan="2" >
<strong><code>EXTERNAL WHITE BALANCE CALIBRATION CALIBRATION</code></strong>
<strong><code>WHITE BALANCE OFFSET CALIBRATION CALIBRATION</code></strong>
</td>
</tr>
<tr>
Expand All @@ -1422,7 +1426,7 @@ However, in this case the calibration plate is white balanced towards an externa
<img src="docs/source/images/image18.png" alt="image_tooltip" width="60%" height="50%">


Once applied, the gray patches on the right hand of the viewer will show the before and after the external white point shift calibration.
Once applied, the gray patches on the right hand of the viewer will show the before and after the white point offset calibration.


#### EXPORT CALIBRATION
Expand Down Expand Up @@ -1686,4 +1690,3 @@ Thank you all for your support and collaboration.




Binary file removed User_Guide_OpenVPCal.pdf
Binary file not shown.
9 changes: 5 additions & 4 deletions compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,13 @@ def check_python_is_64_bit() -> bool:


def check_python_version() -> bool:
""" Checks the version of python we have installed is 3.11.6
""" Checks the version of python we have installed is 3.11
Returns: True if python is 3.11.6, False if not
Returns: True if python is 3.11, False if not
"""
return '3.11.6' == platform.python_version()
major_minor_version = '.'.join(platform.python_version().split('.')[:2])
return '3.11' == major_minor_version


def is_git_installed() -> bool:
Expand Down Expand Up @@ -555,7 +556,7 @@ def check_dependencies() -> None:
if not check_python_is_64_bit():
raise RuntimeError("Python must be 64 bit")
if not check_python_version():
raise RuntimeError("Python must be 3.11.6")
raise RuntimeError("Python must be 3.11")
if not is_git_installed():
raise RuntimeError("Git must be installed")
if not is_pkgconfig_installed():
Expand Down
80 changes: 80 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: OpenVPCal
channels:
- conda-forge
- defaults
- pytorch-nightly
dependencies:
- python=3.11
- conda-forge::openimageio=2.5.9.0
- conda-forge::py-openimageio=2.5.9.0
- pip:
- alabaster==0.7.13
- altgraph==0.17.4
- astroid==3.0.2
- Babel==2.14.0
- certifi==2024.7.4
- charset-normalizer==3.3.2
- colour-checker-detection==0.1.5
- colour-science==0.4.3
- contourpy==1.2.0
- coverage==7.3.3
- cycler==0.12.1
- dill==0.3.7
- docutils==0.20.1
- execnet==2.0.2
- flake8==6.1.0
- fonttools==4.46.0
- idna==3.7
- imageio==2.33.1
- imagesize==1.4.1
- importlib-resources==6.1.1
- iniconfig==2.0.0
- isort==5.13.2
- Jinja2==3.1.4
- kiwisolver==1.4.5
- lazy-object-proxy==1.9.0
- macholib==1.16.3
- MarkupSafe==2.1.3
- matplotlib==3.8.2
- mccabe==0.7.0
- numpy==1.26.2
- opencolorio==2.3.1
- opencv-python==4.8.1.78
- packaging==23.2
- pillow==10.3.0
- platformdirs==4.1.0
- pluggy==1.3.0
- pycodestyle==2.11.1
- pyflakes==3.1.0
- Pygments==2.17.2
- pyinstaller==6.3.0
- pyinstaller-hooks-contrib==2023.10
- pylint==3.0.3
- pyparsing==3.1.1
- pyqtgraph==0.13.3
- PySide6==6.5.3
- PySide6-Addons==6.5.3
- PySide6-Essentials==6.5.3
- pytest==7.4.3
- pytest-xdist==3.5.0
- python-dateutil==2.8.2
- requests==2.32.0
- scipy==1.11.4
- shiboken6==6.5.3
- six==1.16.0
- snowballstemmer==2.2.0
- Sphinx==7.2.6
- sphinx-rtd-theme==2.0.0
- sphinxcontrib-applehelp==1.0.7
- sphinxcontrib-devhelp==1.0.5
- sphinxcontrib-htmlhelp==2.0.4
- sphinxcontrib-jquery==4.1
- sphinxcontrib-jsmath==1.0.1
- sphinxcontrib-qthelp==1.0.6
- sphinxcontrib-serializinghtml==1.1.9
- tomli==2.0.1
- tomlkit==0.12.3
- typing_extensions==4.9.0
- urllib3==2.2.2
- wrapt==1.16.0
- zipp==3.19.1
12 changes: 6 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ alabaster==0.7.13
altgraph==0.17.4
astroid==3.0.2
Babel==2.14.0
certifi==2023.11.17
certifi==2024.7.4
charset-normalizer==3.3.2
colour-checker-detection==0.1.5
colour-science==0.4.3
Expand All @@ -20,7 +20,7 @@ imagesize==1.4.1
importlib-resources==6.1.1
iniconfig==2.0.0
isort==5.13.2
Jinja2==3.1.3
Jinja2==3.1.4
kiwisolver==1.4.5
lazy-object-proxy==1.9.0
macholib==1.16.3
Expand All @@ -31,7 +31,7 @@ numpy==1.26.2
opencolorio==2.3.1
opencv-python==4.8.1.78
packaging==23.2
Pillow==10.3.0
pillow==10.3.0
platformdirs==4.1.0
pluggy==1.3.0
pycodestyle==2.11.1
Expand All @@ -48,7 +48,7 @@ PySide6-Essentials==6.5.3
pytest==7.4.3
pytest-xdist==3.5.0
python-dateutil==2.8.2
requests==2.31.0
requests==2.32.0
scipy==1.11.4
shiboken6==6.5.3
six==1.16.0
Expand All @@ -65,6 +65,6 @@ sphinxcontrib-serializinghtml==1.1.9
tomli==2.0.1
tomlkit==0.12.3
typing_extensions==4.9.0
urllib3==2.1.0
urllib3==2.2.2
wrapt==1.16.0
zipp==3.17.0
zipp==3.19.1
2 changes: 1 addition & 1 deletion src/open_vp_cal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
Init Module defines a few module level variables
"""
__version__ = "1.0.0-rc.12"
__version__ = "1.2.0"
__authors__ = [
"Adam Davis", "Adrian Pueyo", "Carol Payne", "Francesco Luigi Giardiello", "Daniel Heckenberg"
]
Expand Down
11 changes: 3 additions & 8 deletions src/open_vp_cal/application_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,6 @@ def run_pre_checks(self, led_walls: List[LedWallSettings]) -> bool:
"""
led_wall_names = [led_wall.name for led_wall in led_walls]
for led_wall in led_walls:
if led_wall.native_camera_gamut == led_wall.target_gamut:
message = f"Target Gamut & Native Camera Gamut Can Not Be The Same For {led_wall.name}"
self.error_message(message)
return False

if not led_wall.has_valid_white_balance_options():
message = f"Only Select 1 option from AutoWB, or Reference Wall or External White {led_wall.name}"
self.error_message(message)
Expand All @@ -139,12 +134,12 @@ def run_pre_checks(self, led_walls: List[LedWallSettings]) -> bool:
self.error_message(message)
return False

if led_wall.use_external_white_point:
if not led_wall.external_white_point_file:
if led_wall.use_white_point_offset:
if not led_wall.white_point_offset_source:
self.error_message(f"External White Point Enabled But File Not Set {led_wall.name}")
return False

if not os.path.exists(led_wall.external_white_point_file):
if not os.path.exists(led_wall.white_point_offset_source):
self.error_message(f"External White Point File Set Does Not Exist {led_wall.name}")
return False

Expand Down
8 changes: 4 additions & 4 deletions src/open_vp_cal/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,15 @@ class LedWallSettingsKeys:
TARGET_TO_SCREEN_CAT = "target_to_screen_cat"
MATCH_REFERENCE_WALL = "match_reference_wall"
REFERENCE_WALL = "reference_wall"
EXTERNAL_WHITE_POINT_FILE = "external_white_point_file"
USE_EXTERNAL_WHITE_POINT = "use_external_white_point"
WHITE_POINT_OFFSET_SOURCE = "white_point_offset_source"
USE_WHITE_POINT_OFFSET = "use_white_point_offset"
IS_VERIFICATION_WALL = "is_verification_wall"
VERIFICATION_WALL = "verification_wall"
ALL = [NAME, ENABLE_EOTF_CORRECTION, ENABLE_GAMUT_COMPRESSION, AUTO_WB_SOURCE, INPUT_SEQUENCE_FOLDER,
NUM_GREY_PATCHES, PRIMARIES_SATURATION, CALCULATION_ORDER, INPUT_PLATE_GAMUT, NATIVE_CAMERA_GAMUT,
REFERENCE_TO_TARGET_CAT, ROI, SHADOW_ROLLOFF, TARGET_MAX_LUM_NITS, TARGET_GAMUT, TARGET_EOTF,
TARGET_TO_SCREEN_CAT, MATCH_REFERENCE_WALL, REFERENCE_WALL, USE_EXTERNAL_WHITE_POINT,
EXTERNAL_WHITE_POINT_FILE, VERIFICATION_WALL, IS_VERIFICATION_WALL, AVOID_CLIPPING]
TARGET_TO_SCREEN_CAT, MATCH_REFERENCE_WALL, REFERENCE_WALL, USE_WHITE_POINT_OFFSET,
WHITE_POINT_OFFSET_SOURCE, VERIFICATION_WALL, IS_VERIFICATION_WALL, AVOID_CLIPPING]


class PATCHES:
Expand Down
35 changes: 26 additions & 9 deletions src/open_vp_cal/framework/auto_roi.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
import sys
from typing import List


from open_vp_cal.core.utils import clamp
from open_vp_cal.led_wall_settings import LedWallSettings


from open_vp_cal.imaging import imaging_utils
from open_vp_cal.framework.sample_patch import BaseSamplePatch
from open_vp_cal.framework.identify_separation import SeparationResults
from open_vp_cal.core import constants
Expand All @@ -32,6 +33,7 @@ class AutoROIResults:
"""
Class to store the results of the roi detection
"""

def __init__(self):
"""
Initialize an instance of AutoROIResults.
Expand Down Expand Up @@ -144,14 +146,17 @@ class AutoROI(BaseSamplePatch):
The main class which deals with identifying the region of interest within the image sequence which we want to
extract
"""
def __init__(self, led_wall_settings: LedWallSettings, separation_results: SeparationResults):

def __init__(self, led_wall_settings: LedWallSettings,
separation_results: SeparationResults):
""" Initialize an instance of AutoROI
Args:
led_wall_settings: The LED wall we want to detect the roi for
separation_results: The results of the separation detection for the LED wall sequence
"""
super().__init__(led_wall_settings, separation_results, constants.PATCHES.DISTORT_AND_ROI)
super().__init__(led_wall_settings, separation_results,
constants.PATCHES.DISTORT_AND_ROI)

def run(self) -> AutoROIResults:
"""
Expand All @@ -166,12 +171,22 @@ def run(self) -> AutoROIResults:
if first_patch_frame > self.led_wall.sequence_loader.end_frame:
return results

frame = self.led_wall.sequence_loader.get_frame(first_patch_frame + self.trim_frames)
frame = self.led_wall.sequence_loader.get_frame(
first_patch_frame + self.trim_frames)

pixel_buffer = 5
detection_threshold = 1.7
for y_pos in range(frame.image_buf.spec().height):
for x_pos in range(frame.image_buf.spec().width):
pixel = frame.image_buf.getpixel(x_pos, y_pos)

# Create the white balance matrix
white_balance_matrix = self.get_white_balance_matrix_from_slate()

# Apply the white balance matrix to the frame
balanced_image = imaging_utils.apply_matrix_to_img_buf(
frame.image_buf, white_balance_matrix
)
for y_pos in range(balanced_image.spec().height):
for x_pos in range(balanced_image.spec().width):
pixel = balanced_image.getpixel(x_pos, y_pos)
red = clamp(pixel[0], 0, sys.float_info.max)
green = clamp(pixel[1], 0, sys.float_info.max)
blue = clamp(pixel[2], 0, sys.float_info.max)
Expand All @@ -183,12 +198,14 @@ def run(self) -> AutoROIResults:

if green > results.green_value:
if green > max(red, blue) * detection_threshold:
results.green_pixel = (x_pos - pixel_buffer, y_pos + pixel_buffer)
results.green_pixel = (
x_pos - pixel_buffer, y_pos + pixel_buffer)
results.green_value = green

if blue > results.blue_value:
if blue > max(red, green) * detection_threshold:
results.blue_pixel = (x_pos + pixel_buffer, y_pos - pixel_buffer)
results.blue_pixel = (
x_pos + pixel_buffer, y_pos - pixel_buffer)
results.blue_value = blue

white = (red + green + blue) / 3
Expand Down
Loading

0 comments on commit c67444a

Please sign in to comment.