Skip to content

Commit ccfd0dc

Browse files
authored
Adding Colorblind filters (#8)
* Adding Colorblind filters * Fix pipeline
1 parent 0b1be72 commit ccfd0dc

57 files changed

Lines changed: 2095 additions & 590 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/c-cpp.yml

Lines changed: 10 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,62 +31,28 @@ jobs:
3131
run: echo "CURRENT_OS=$(echo $RUNNER_OS | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
3232
shell: bash
3333

34-
- name: Set up cache
35-
uses: actions/github-script@v7
36-
with:
37-
script: |
38-
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
39-
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
40-
4134
- uses: actions/checkout@v4
4235

43-
- name: Create vcpkg default binary cache
44-
run: |
45-
if [ "$RUNNER_OS" == "Windows" ]; then
46-
mkdir -p ${{ github.workspace }}\vcpkg\bincache
47-
else
48-
mkdir -p ${{ github.workspace }}/vcpkg/bincache
49-
fi
50-
shell: bash
51-
5236
- name: Install packages
5337
if: runner.os == 'Linux'
54-
run: sudo apt-get install -y libxi-dev libxtst-dev bison gperf libgles2-mesa-dev libxrandr-dev libxcursor-dev libxdamage-dev libxinerama-dev nasm autoconf automake libtool pkg-config libltdl-dev
38+
run: sudo apt-get update && sudo apt-get install -y autoconf-archive automake libxtst-dev bison gperf libgles2-mesa-dev libxrandr-dev libxcursor-dev libxdamage-dev libxinerama-dev nasm autoconf automake libtool pkg-config libltdl-dev
5539

5640
- if: runner.os == 'macOS'
5741
run: brew install nasm
5842

5943
- uses: lukka/get-cmake@v3.26.0
6044

6145
- name: Set up vcpkg
62-
uses: lukka/run-vcpkg@v4
63-
with:
64-
setupOnly: true
65-
vcpkgGitCommitId: d320630b28aeb59b24424eb2a7ef3905314107a1
66-
67-
# Restore vpkg cache
68-
- name: Restore vcpkg
69-
uses: actions/cache@v4
46+
uses: lukka/run-vcpkg@v11
7047
with:
71-
path: |
72-
${{ env._VCPKG_ }}
73-
!${{ env._VCPKG_ }}/buildtrees
74-
!${{ env._VCPKG_ }}/packages
75-
!${{ env._VCPKG_ }}/downloads
76-
!${{ env._VCPKG_ }}/installed
77-
key: |
78-
${{ hashFiles( '.git/modules/vcpkg/HEAD' )}}
79-
80-
# Ensure that the developer command promt is present on Windows runners
81-
- uses: ilammy/msvc-dev-cmd@v1
82-
83-
- name: Restore from cache the dependencies and generate project files
84-
run: |
85-
cmake -DBUILD_EXAMPLE_APP=ON -DBUILD_TESTS=ON --preset ${{ env.CURRENT_OS }}-release
48+
vcpkgGitCommitId: 4c4abc2e8727221ede31021349386dac674309b0
8649

87-
- name: Build (Release configuration)
88-
run: |
89-
cmake --build --preset ${{ env.CURRENT_OS }}-release
50+
- name: Run CMake consuming CMakePreset.json and run vcpkg to build packages
51+
uses: lukka/run-cmake@v10
52+
with:
53+
configurePreset: ${{ env.CURRENT_OS }}-release
54+
configurePresetAdditionalArgs: "['-DBUILD_EXAMPLE_APP=ON','-DBUILD_TESTS=ON']"
55+
buildPreset: ${{ env.CURRENT_OS }}-release
9056

9157
- name: Upload build artifacts
9258
uses: actions/upload-artifact@v4
@@ -150,4 +116,4 @@ jobs:
150116
- name: Test
151117
run: |
152118
ctest --preset test-${{ env.CURRENT_OS }}
153-
119+

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ source_group("Public header files" FILES ${PUBLIC_HEADERS})
5555

5656
set(SOURCE_FILES
5757
"src/Configuration.cpp"
58+
"src/ColorblindFilters.cpp"
5859
"src/IChecker.h"
5960
"src/ITextboxDetection.h"
6061
"src/ITextboxDetection.cpp"

CMakePresets.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,6 @@
171171
"configurePreset": "linux-debug",
172172
"inherits": "core-build"
173173
},
174-
{
175-
"name": "code-coverage",
176-
"configurePreset": "linux-debug",
177-
"inherits": "core-build",
178-
"targets": "coverage"
179-
},
180174
{
181175
"name": "linux-release",
182176
"configurePreset": "linux-release",

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ When running Fonttik the following optional arguments can be passed to alter the
5858

5959
- `-c`: Specify configuration file. Given a path to a specific configuration file uses that one during this execution. By default Fonttik looks for config.json in its own folder.
6060
- `-a`: Store results as the analysis runs asynchronously
61+
## Notes on Colorblindness simulation filters
62+
Fonttik now includes colorblindness filters that simulate how text may appear to users with a color vision deficiency. The filters support simulation of the three main types of color vision deficiency; Protanopia (red cone deficiency), Deuteranopia (green cone deficiency), Tritanopia (blue cone deficiency), in addition to a Grayscale filter. These filters are integrated into the image analysis process by default, but are not available for video analysis. Fonttik processes each image through each filter to generate contrast results for each filter type, showing the detected text boxes overlaid on the simulated versions of the original image. The colorblindness simulation is only applied to the contrast checks.
6163

6264
## Configuration
6365

@@ -123,3 +125,9 @@ Fonttik utilizes open source software, see [NOTICE](./NOTICE.txt) licenses and d
123125
## CONTRIBUTING
124126

125127
Before you can contribute, EA must have a Contributor License Agreement (CLA) on file that has been signed by each contributor. You can sign here: [CLA](https://electronicarts.na1.echosign.com/public/esignWidget?wid=CBFCIBAA3AAABLblqZhByHRvZqmltGtliuExmuV-WNzlaJGPhbSRg2ufuPsM3P0QmILZjLpkGslg24-UJtek*)
128+
129+
## Special thanks
130+
#### To the interns that have worked on this project:
131+
- Adrian Alvarez Bernabe
132+
- Esteban Restrepo Gutierrez
133+
- Paula Antequera Hernandez

config/config.json

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@
7171
"x": 0.3,
7272
"y": 0.75
7373
},
74-
"preferredBackend": "CUDA",
75-
"preferredTarget": "CUDA",
74+
"preferredBackend": "default",
75+
"preferredTarget": "default",
7676
"DB_EAST": {
7777
"detectionModel": "frozen_east_text_detection.pb",
7878
"nmsThreshold": 0.4,
@@ -127,6 +127,33 @@
127127
}
128128
}
129129
},
130+
"colorblindness": {
131+
"linearRGBToXYZJuddVosMatrix": [
132+
[ 40.9568, 35.5041, 17.9167 ],
133+
[ 21.3389, 70.6743, 7.98680 ],
134+
[ 1.86297, 11.4620, 91.2367 ]
135+
],
136+
"XYZJuddVosToLMSMatrix": [
137+
[ 0.15514, 0.54312, -0.03286 ],
138+
[ -0.15514, 0.45684, 0.03286 ],
139+
[ 0.00000, 0.00000, 0.01608 ]
140+
],
141+
"LMSToLinearRGBMatrix": [
142+
[ 0.080944, -0.130504, 0.116721 ],
143+
[ -0.0102485, 0.0540194, -0.113615 ],
144+
[ -0.000365294, -0.00412163, 0.693513 ]
145+
],
146+
"protanProjectionMatrix": [
147+
[ 0.00000, 2.02344, -2.52581 ],
148+
[ 0.00000, 1.00000, 0.00000 ],
149+
[ 0.00000, 0.00000, 1.00000 ]
150+
],
151+
"deutanProjectionMatrix": [
152+
[ 1.00000, 0.00000, 0.00000 ],
153+
[ 0.494207, 0.00000, 1.24827 ],
154+
[ 0.00000, 0.00000, 1.00000 ]
155+
]
156+
},
130157
"sRGBLinearizationValues": [
131158
0,
132159
0.000303527,
@@ -385,4 +412,4 @@
385412
0.9911022,
386413
1
387414
]
388-
}
415+
}

example/main.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ bool cmdOptionExists(char** begin, char** end, const std::string& option)
3131

3232
void processMedia(tik::Fonttik& fonttik, fs::path path, tik::Configuration& config, bool async)
3333
{
34-
tik::Media* media = tik::Media::createMedia(path.string());
34+
tik::Media* media = tik::Media::createMedia(path.string(), fonttik.colorblindFilters);
3535

3636
if (media != nullptr)
3737
{
@@ -74,21 +74,14 @@ void processFolder(tik::Fonttik& fonttik, fs::path path, tik::Configuration& con
7474
}
7575

7676

77-
ushort median(cv::Mat m) {
78-
auto b = m.begin<ushort>();
79-
auto mi = b + (m.total() / 2);
80-
auto e = m.end<ushort>();
81-
std::nth_element(b, mi, e);
82-
return *mi;
83-
}
84-
85-
8677
int main(int argc, char* argv[]) {
8778
tik::Log::InitCoreLogger(true, false, 1, nullptr, "%^[%l] %v%$");
8879
LOG_CORE_WARNING("Note: The results shown in this report are for informational purposes only, and should not be used as a certification or validation of compliance with any legal, regulatory or other requirements.");
8980

9081
LOG_CORE_TRACE("Executing in {0}", std::filesystem::current_path().string());
9182

83+
std::cout << cv::getBuildInformation() << std::endl;
84+
9285
bool async = cmdOptionExists(argv, argv + argc, "-a");
9386

9487
fs::path path;
@@ -138,7 +131,7 @@ int main(int argc, char* argv[]) {
138131
}
139132

140133
fonttik.init(&config);
141-
134+
142135
if (fs::exists(path) || path.string().rfind("http",0)==0/*begins with http*/ ) {
143136

144137
if (!fs::is_directory(path)) {

include/fonttik/Configuration.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ class Configuration
3030
inline const ContrastRatioParams& getContrastRatioParams() const { return contrastRatioParams; }
3131
inline const TextSizeParams& getTextSizeParams() const { return textSizeParams; }
3232
inline const std::vector<double>& getSbgrValues() const { return sBgrValues; }
33+
inline const cv::Mat& getLinearRGBToLMSMatrix() const { return linearRGBToLMSMatrix; }
34+
inline const cv::Mat& getXYZJuddVosToLMSMatrix() const { return XYZJuddVosToLMSMatrix; }
35+
inline const cv::Mat& getLMSToLinearRGBMatrix() const { return LMSToLinearRGBMatrix; }
36+
inline const cv::Mat& getProtanProjectionMatrix() const { return protanProjectionMatrix; }
37+
inline const cv::Mat& getDeutanProjectionMatrix() const { return deutanProjectionMatrix; }
3338
const std::vector<cv::Scalar> getOutlineColors() const { return outlineColors; }
3439

3540
inline void setAnalysisWaitSeconds(const int& aws) { appSettings.analysisWaitSeconds = aws; }
@@ -52,7 +57,7 @@ class Configuration
5257
}
5358
inline void setUseOcr(const bool useOcr) { textSizeParams.useTextRecognition = useOcr; }
5459
inline void setTreatFailsAsWarnings(const bool failsAsWarnings) { appSettings.failsAsWarnings = failsAsWarnings; }
55-
inline void setContrastRatio(const int& cr) { contrastRatioParams.contrastRatio = cr; }
60+
inline void setContrastRatio(const float cr) { contrastRatioParams.contrastRatio = cr; }
5661
inline void setSizeGuideline(const std::string& height, const SizeGuidelines& sg) { textSizeParams.resolutionGuidelines[height] = sg; }
5762
inline void setSizeByLine(bool sizeByLine) { appSettings.sizeByLine = sizeByLine; }
5863

@@ -69,6 +74,7 @@ class Configuration
6974
void loadTextSizeParams(const json& section, const json& section2);
7075
void loadEASTParams(const json& section);
7176
void loadDiffBinarizationParams(const json& section);
77+
cv::Mat loadMatrix(const json& section);
7278
std::unordered_map<std::string, SizeGuidelines> loadSizeGuidelines(const json& section);
7379

7480
/// <summary>
@@ -88,6 +94,12 @@ class Configuration
8894
ContrastRatioParams contrastRatioParams;
8995
TextSizeParams textSizeParams;
9096

97+
cv::Mat linearRGBToXYZJuddVosMatrix;
98+
cv::Mat XYZJuddVosToLMSMatrix;
99+
cv::Mat linearRGBToLMSMatrix;
100+
cv::Mat LMSToLinearRGBMatrix;
101+
cv::Mat protanProjectionMatrix;
102+
cv::Mat deutanProjectionMatrix;
91103
std::vector<double> sBgrValues;
92104
std::vector<cv::Scalar> outlineColors;
93105
};

include/fonttik/ConfigurationParams.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//Copyright (C) 2022-2025 Electronic Arts, Inc. All rights reserved.
1+
//Copyright (C) 2022 Electronic Arts, Inc. All rights reserved.
22
#pragma once
33

44
#include <array>

include/fonttik/Fonttik.hpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
#include <filesystem>
55
#include <opencv2/core/mat.hpp>
66
namespace fs = std::filesystem;
7-
7+
#include "Results.h"
8+
#include "../src/ColorblindFilters.hpp"
89

910
namespace tik
1011
{
@@ -25,8 +26,18 @@ struct AsyncResults
2526
fs::path pathToContrastResult;
2627
fs::path pathToJSONSizeResult;
2728
fs::path pathToJSONContrastResult;
29+
30+
fs::path pathToProtanResult;
31+
fs::path pathToDeutanResult;
32+
fs::path pathToTritanResult;
33+
fs::path pathToGrayscaleResult;
34+
2835
bool overAllPassSize = true;
36+
tik::ResultType overAllResultSize = PASS;
2937
bool overAllPassContrast = true;
38+
tik::ResultType overAllResultContrast = PASS;
39+
std::vector<bool> overallPassColorblind = { true, true, true, true };
40+
std::vector<ResultType> overallResultColorblind = { PASS, PASS, PASS, PASS };
3041
};
3142

3243

@@ -44,12 +55,14 @@ class Fonttik
4455

4556
Results processMedia(Media& media);
4657

47-
std::pair<FrameResults, FrameResults> processFrame(Frame& frame, bool sizeByLine);
48-
58+
std::pair<FrameResults, FrameResults> processFrame(Frame& frame, std::vector<Frame> colorblindFrames, bool sizeByLine);
59+
4960
std::pair<fs::path, fs::path> saveResults(Media& media, Results& results);
5061

5162
std::pair<fs::path, fs::path> saveResultsToJson(fs::path outputPath, Results& results);
5263

64+
ColorblindFilters* colorblindFilters = nullptr;
65+
5366
private:
5467
bool setResolutionGuideline(const Media& media);
5568

@@ -59,6 +72,8 @@ class Fonttik
5972

6073
void calculateTextMasks(std::vector<TextBox>& textBoxes);
6174

75+
std::vector<std::vector<TextBox>> createColorblindTextBoxes(std::vector<Frame> colorblindFrames, std::vector<TextBox> words);
76+
6277
/// <summary>
6378
/// Sets the recognized text in the contrast results
6479
/// </summary>

include/fonttik/Frame.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class Frame {
3333
static void paintTextBox(const int& x1, const int& y1, const int& x2, const int& y2, cv::Scalar& color, cv::Mat& image, int thickness = 1);
3434

3535
//Paints output value from a resultbox next to itself in an image
36-
static void paintTextBoxResultValues(cv::Mat& image, const ResultBox& box, int precision);
36+
static void paintTextBoxResultValues(cv::Mat& image, const ResultBox& box, double value, int precision);
3737

3838
virtual ~Frame();
3939

0 commit comments

Comments
 (0)