Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start adding in a ci workflow #36

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8b6414f
Start adding in a ci workflow
davisadam10 May 1, 2024
4af7b09
Test this on main
davisadam10 May 1, 2024
79f4659
Enabling lfs and adding in the build dev command
davisadam10 May 1, 2024
9352155
Fix: The macbeth chart sampling so that we do the detection in sRGB-D…
davisadam10 Jul 23, 2024
eaf5e42
up version for next round of development
davisadam10 Jul 23, 2024
6116456
disable avoid clipping by default
davisadam10 Jul 24, 2024
f6255a3
Fix: Clarify the validation messages so they are more human readable
davisadam10 Jul 24, 2024
d8039f5
Fix: To improve the macbeth detection we normalize the images into a …
davisadam10 Jul 24, 2024
99dff81
Fix: Add methods to calculate white balance from the slate, and apply…
davisadam10 Jul 27, 2024
8c424c9
Fix: Reduce the inner black boader of the 18% patch on the slate to a…
davisadam10 Jul 27, 2024
cd01fe6
Merge branch 'main' into dev
davisadam10 Jul 27, 2024
7b414d6
adjust border thickness to two pixels wide
davisadam10 Jul 27, 2024
83c5d3a
Add in a conda environment for easier building as this handles everyt…
davisadam10 Aug 2, 2024
c67444a
Merge branch 'dev' into feature/ci
davisadam10 Aug 2, 2024
0f9022c
Simplify the ci/cd workflow
davisadam10 Aug 2, 2024
54c05a8
Try and fix this
davisadam10 Aug 3, 2024
2e221c8
disable the lfs for now as we are running out of disk space and we tr…
davisadam10 Aug 3, 2024
d90a33f
Try building on mac
davisadam10 Aug 3, 2024
ea236fd
Update the version
davisadam10 Aug 3, 2024
cb7b7f7
try and run the unit tests
davisadam10 Aug 3, 2024
ac74be7
Try again
davisadam10 Aug 3, 2024
22762af
Try again
davisadam10 Aug 3, 2024
2baf4d2
Forget conda as wont work on windows because of oiio
davisadam10 Aug 3, 2024
289c2bb
Add in the build dev step
davisadam10 Aug 3, 2024
dbdf45d
Add in the build step
davisadam10 Aug 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Python CI/CD Workflow

on:
push:
branches:
- feature/ci
pull_request:
branches:
- feature/ci

jobs:
build_macos:
runs-on: macos-latest

steps:
# Restore the .git directory from the cache
- name: Cache repository
uses: actions/cache@v3
with:
path: .git
key: ${{ runner.os }}-git-${{ hashFiles('.git/HEAD') }}
restore-keys: |
${{ runner.os }}-git-

# Check out the repository without LFS support
- name: Check out repository
uses: actions/checkout@v3
with:
lfs: false # Disable Git LFS

# Set up Python 3.11
- name: Set up Python 3.11
uses: actions/setup-python@v2
with:
python-version: 3.11

# Install dependencies
# Step 1: Install dependencies
- name: Install dependencies
run: |
brew update
brew install pkg-config autoconf automake autoconf-archive

# Run build_dev.sh script
- name: Run build_dev.sh script
run: |
chmod +x build_dev.sh
./build.sh

81 changes: 81 additions & 0 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
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
- 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
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.1.0"
__version__ = "1.2.0"
__authors__ = [
"Adam Davis", "Adrian Pueyo", "Carol Payne", "Francesco Luigi Giardiello", "Daniel Heckenberg"
]
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
2 changes: 1 addition & 1 deletion src/open_vp_cal/framework/generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ def _add_slate_inner_squares(
"""
patch_roi = Oiio.ROI(start_x, start_x + patch_width, start_y, start_y + patch_height)
inner_edge_roi = self.reduce_roi(patch_roi, 1)
inner_patch_roi = self.reduce_roi(inner_edge_roi, 1)
inner_patch_roi = self.reduce_roi(inner_edge_roi, 0.5)
Oiio.ImageBufAlgo.fill(patch, (self.percent_18_lum, self.percent_18_lum, self.percent_18_lum), roi=patch_roi)
Oiio.ImageBufAlgo.fill(patch, (0.0, 0.0, 0.0), roi=inner_edge_roi)
Oiio.ImageBufAlgo.fill(patch, (self.percent_18_lum, self.percent_18_lum, self.percent_18_lum),
Expand Down
12 changes: 12 additions & 0 deletions src/open_vp_cal/framework/identify_separation.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,22 @@ def _find_first_red_and_green_frames(self) -> None:
distances = []

previous_mean_frame = None

slate_frame = self.led_wall.sequence_loader.get_frame(
self.led_wall.sequence_loader.start_frame
)
white_balance_matrix = imaging_utils.calculate_white_balance_matrix_from_img_buf(
slate_frame.image_buf)

for frame in self.led_wall.sequence_loader:
# Load the image from the frame
image = frame.extract_roi(self.led_wall.roi)

# Apply the white balance matrix to the frame
image = imaging_utils.apply_matrix_to_img_buf(
image, white_balance_matrix
)

# Compute the average for all the values which are above the initial average
mean_color, _ = imaging_utils.get_average_value_above_average(image)
distance = 0
Expand Down
74 changes: 64 additions & 10 deletions src/open_vp_cal/framework/sample_patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
"""
import threading
import numpy as np
from colour_checker_detection.detection.segmentation import \
detect_colour_checkers_segmentation
from colour_checker_detection.detection.segmentation import (
detect_colour_checkers_segmentation)

from open_vp_cal.core.utils import find_factors_pairs
from open_vp_cal.imaging import imaging_utils
from open_vp_cal.core.structures import SamplePatchResults
from open_vp_cal.framework.identify_separation import SeparationResults
Expand Down Expand Up @@ -81,6 +82,20 @@ def calculate_first_and_last_patch_frame(self) -> tuple[int, int]:
self.trim_frames = trim_frames
return first_patch_frame, last_patch_frame

def get_white_balance_matrix_from_slate(self) -> np.ndarray:
""" Get the white balance matrix from the slate frame

Returns:
np.ndarray: The white balance matrix

"""
slate_frame = self.led_wall.sequence_loader.get_frame(
self.led_wall.sequence_loader.start_frame
)
white_balance_matrix = imaging_utils.calculate_white_balance_matrix_from_img_buf(
slate_frame.image_buf)
return white_balance_matrix


class SamplePatch(BaseSamplePatch):
"""
Expand Down Expand Up @@ -239,21 +254,60 @@ def _sample_patch(self) -> None:
# We trim a number of frames off either side of the patch to ensure we remove multiplexing
sample_results = SamplePatchResults()
samples = []
white_balance_matrix = self.get_white_balance_matrix_from_slate()
for frame_num in range(first_patch_frame + self.trim_frames,
(last_patch_frame - self.trim_frames) + 1):
frame = self.led_wall.sequence_loader.get_frame(frame_num)
section = frame.extract_roi(self.led_wall.roi)
sample_results.frames.append(frame)
section_np_array = imaging_utils.image_buf_to_np_array(section)
for colour_checker_swatches_data in detect_colour_checkers_segmentation(
section_np_array, additional_data=True):
swatch_colours, _, _ = (
colour_checker_swatches_data.values)

# Extract our region
section_orig = frame.extract_roi(self.led_wall.roi)

# White balance the images so we increase the detection likelihood of
# success
section_orig = imaging_utils.apply_matrix_to_img_buf(
section_orig, white_balance_matrix
)

section_display_np_array = imaging_utils.image_buf_to_np_array(section_orig)
imaging_utils.apply_color_converstion_to_np_array(
section_display_np_array,
str(self.led_wall.input_plate_gamut),
"ACEScct",
)

# Run the detections
detections = detect_colour_checkers_segmentation(
section_display_np_array, additional_data=True)

for colour_checker_swatches_data in detections:
# Get the swatch colours
swatch_colours, _, _ = colour_checker_swatches_data.values
swatch_colours = np.array(swatch_colours, dtype=np.float32)

# Reshape the number of swatches from a 24, 3 array to an x, y, 3 array
num_swatches = swatch_colours.shape[0]
factor_pairs = find_factors_pairs(num_swatches)
x, y = factor_pairs[0]
array_x_y_3 = swatch_colours.reshape(x, y, 3)

# Convert the colours back to the input plate gamut
imaging_utils.apply_color_converstion_to_np_array(
array_x_y_3,
"ACEScct",
str(self.led_wall.input_plate_gamut))

# Inverse the white balance back to the original values
inv_wb_matrix = np.linalg.inv(white_balance_matrix)
array_x_y_3 = array_x_y_3 @ inv_wb_matrix

# Reshape the array back to a 24, 3 array
swatch_colours = array_x_y_3.reshape(num_swatches, 3)
samples.append(swatch_colours)

# Compute the mean for each tuple index across all tuples, if the detection fails and we get nans, then we
# replace the nans with black patches as these are not used in the calibration directly
# Compute the mean for each tuple index across all tuples, if the
# detection fails, and we get nans, then we replace the nans with black patches
# as these are not used in the calibration directly
averaged_tuple = np.mean(np.array(samples), axis=0)
if not np.isnan(averaged_tuple).any():
sample_results.samples = averaged_tuple.tolist()
Expand Down
7 changes: 3 additions & 4 deletions src/open_vp_cal/framework/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def exposure_validation(calibration_results: Dict) -> ValidationResult:
if measured_18_percent < quarter_stop_down_18_percent or measured_18_percent > quarter_stop_up_18_percent:
result.status = ValidationStatus.FAIL
result.message = (
f"The Measured Exposure: {measured_18_percent}\n"
f"The Exposure of the 18% Patch is measured at {round(measured_18_percent, 1) * 100}%\n"
"It seems that you have not exposed the calibration patches correctly. "
"Please ensure to expose the first 18% patch correctly using the camera false colour or light meter."
)
Expand All @@ -87,8 +87,7 @@ def exposure_validation(calibration_results: Dict) -> ValidationResult:
else:
result.status = ValidationStatus.WARNING
result.message = (
f"The Measured Exposure: {measured_18_percent} is not ideal\n"
"It seems that you have not exposed the calibration patches correctly. "
f"The Exposure of the 18% Patch is measured at {round(measured_18_percent, 1) * 100}%, this is not ideal.\n"
"Please ensure to expose the first 18% patch correctly using the camera false colour or light meter."
)

Expand Down Expand Up @@ -202,7 +201,7 @@ def check_scaled_18_percent(calibration_results: Dict) -> ValidationResult:
if not is_between:
result.status = ValidationStatus.FAIL
result.message = (
f"When scaled the measured 18 percent patch is not within a reasonable range: {scaled_18_percent_nits}."
f"When scaled the measured 18 percent patch is not within a reasonable range: {round(scaled_18_percent_nits, 1)} nits."
" Please check that the wall settings match the actual peak luminance of your wall also check your "
"imaging chain from content engine to LED processor and re shoot the plates"
)
Expand Down
Loading
Loading