Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 10 additions & 44 deletions .github/workflows/c-cpp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,62 +31,28 @@ jobs:
run: echo "CURRENT_OS=$(echo $RUNNER_OS | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
shell: bash

- name: Set up cache
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');

- uses: actions/checkout@v4

- name: Create vcpkg default binary cache
run: |
if [ "$RUNNER_OS" == "Windows" ]; then
mkdir -p ${{ github.workspace }}\vcpkg\bincache
else
mkdir -p ${{ github.workspace }}/vcpkg/bincache
fi
shell: bash

- name: Install packages
if: runner.os == 'Linux'
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
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

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

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

- name: Set up vcpkg
uses: lukka/run-vcpkg@v4
with:
setupOnly: true
vcpkgGitCommitId: d320630b28aeb59b24424eb2a7ef3905314107a1

# Restore vpkg cache
- name: Restore vcpkg
uses: actions/cache@v4
uses: lukka/run-vcpkg@v11
with:
path: |
${{ env._VCPKG_ }}
!${{ env._VCPKG_ }}/buildtrees
!${{ env._VCPKG_ }}/packages
!${{ env._VCPKG_ }}/downloads
!${{ env._VCPKG_ }}/installed
key: |
${{ hashFiles( '.git/modules/vcpkg/HEAD' )}}

# Ensure that the developer command promt is present on Windows runners
- uses: ilammy/msvc-dev-cmd@v1

- name: Restore from cache the dependencies and generate project files
run: |
cmake -DBUILD_EXAMPLE_APP=ON -DBUILD_TESTS=ON --preset ${{ env.CURRENT_OS }}-release
vcpkgGitCommitId: 4c4abc2e8727221ede31021349386dac674309b0

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

- name: Upload build artifacts
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -150,4 +116,4 @@ jobs:
- name: Test
run: |
ctest --preset test-${{ env.CURRENT_OS }}


1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ source_group("Public header files" FILES ${PUBLIC_HEADERS})

set(SOURCE_FILES
"src/Configuration.cpp"
"src/ColorblindFilters.cpp"
"src/IChecker.h"
"src/ITextboxDetection.h"
"src/ITextboxDetection.cpp"
Expand Down
6 changes: 0 additions & 6 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,6 @@
"configurePreset": "linux-debug",
"inherits": "core-build"
},
{
"name": "code-coverage",
"configurePreset": "linux-debug",
"inherits": "core-build",
"targets": "coverage"
},
{
"name": "linux-release",
"configurePreset": "linux-release",
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ When running Fonttik the following optional arguments can be passed to alter the

- `-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.
- `-a`: Store results as the analysis runs asynchronously
## Notes on Colorblindness simulation filters
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.

## Configuration

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

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*)

## Special thanks
#### To the interns that have worked on this project:
- Adrian Alvarez Bernabe
- Esteban Restrepo Gutierrez
- Paula Antequera Hernandez
33 changes: 30 additions & 3 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
"x": 0.3,
"y": 0.75
},
"preferredBackend": "CUDA",
"preferredTarget": "CUDA",
"preferredBackend": "default",
"preferredTarget": "default",
"DB_EAST": {
"detectionModel": "frozen_east_text_detection.pb",
"nmsThreshold": 0.4,
Expand Down Expand Up @@ -127,6 +127,33 @@
}
}
},
"colorblindness": {
"linearRGBToXYZJuddVosMatrix": [
[ 40.9568, 35.5041, 17.9167 ],
[ 21.3389, 70.6743, 7.98680 ],
[ 1.86297, 11.4620, 91.2367 ]
],
"XYZJuddVosToLMSMatrix": [
[ 0.15514, 0.54312, -0.03286 ],
[ -0.15514, 0.45684, 0.03286 ],
[ 0.00000, 0.00000, 0.01608 ]
],
"LMSToLinearRGBMatrix": [
[ 0.080944, -0.130504, 0.116721 ],
[ -0.0102485, 0.0540194, -0.113615 ],
[ -0.000365294, -0.00412163, 0.693513 ]
],
"protanProjectionMatrix": [
[ 0.00000, 2.02344, -2.52581 ],
[ 0.00000, 1.00000, 0.00000 ],
[ 0.00000, 0.00000, 1.00000 ]
],
"deutanProjectionMatrix": [
[ 1.00000, 0.00000, 0.00000 ],
[ 0.494207, 0.00000, 1.24827 ],
[ 0.00000, 0.00000, 1.00000 ]
]
},
"sRGBLinearizationValues": [
0,
0.000303527,
Expand Down Expand Up @@ -385,4 +412,4 @@
0.9911022,
1
]
}
}
15 changes: 4 additions & 11 deletions example/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ bool cmdOptionExists(char** begin, char** end, const std::string& option)

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

if (media != nullptr)
{
Expand Down Expand Up @@ -74,21 +74,14 @@ void processFolder(tik::Fonttik& fonttik, fs::path path, tik::Configuration& con
}


ushort median(cv::Mat m) {
auto b = m.begin<ushort>();
auto mi = b + (m.total() / 2);
auto e = m.end<ushort>();
std::nth_element(b, mi, e);
return *mi;
}


int main(int argc, char* argv[]) {
tik::Log::InitCoreLogger(true, false, 1, nullptr, "%^[%l] %v%$");
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.");

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

std::cout << cv::getBuildInformation() << std::endl;

bool async = cmdOptionExists(argv, argv + argc, "-a");

fs::path path;
Expand Down Expand Up @@ -138,7 +131,7 @@ int main(int argc, char* argv[]) {
}

fonttik.init(&config);

if (fs::exists(path) || path.string().rfind("http",0)==0/*begins with http*/ ) {

if (!fs::is_directory(path)) {
Expand Down
14 changes: 13 additions & 1 deletion include/fonttik/Configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ class Configuration
inline const ContrastRatioParams& getContrastRatioParams() const { return contrastRatioParams; }
inline const TextSizeParams& getTextSizeParams() const { return textSizeParams; }
inline const std::vector<double>& getSbgrValues() const { return sBgrValues; }
inline const cv::Mat& getLinearRGBToLMSMatrix() const { return linearRGBToLMSMatrix; }
inline const cv::Mat& getXYZJuddVosToLMSMatrix() const { return XYZJuddVosToLMSMatrix; }
inline const cv::Mat& getLMSToLinearRGBMatrix() const { return LMSToLinearRGBMatrix; }
inline const cv::Mat& getProtanProjectionMatrix() const { return protanProjectionMatrix; }
inline const cv::Mat& getDeutanProjectionMatrix() const { return deutanProjectionMatrix; }
const std::vector<cv::Scalar> getOutlineColors() const { return outlineColors; }

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

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

/// <summary>
Expand All @@ -88,6 +94,12 @@ class Configuration
ContrastRatioParams contrastRatioParams;
TextSizeParams textSizeParams;

cv::Mat linearRGBToXYZJuddVosMatrix;
cv::Mat XYZJuddVosToLMSMatrix;
cv::Mat linearRGBToLMSMatrix;
cv::Mat LMSToLinearRGBMatrix;
cv::Mat protanProjectionMatrix;
cv::Mat deutanProjectionMatrix;
std::vector<double> sBgrValues;
std::vector<cv::Scalar> outlineColors;
};
Expand Down
2 changes: 1 addition & 1 deletion include/fonttik/ConfigurationParams.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//Copyright (C) 2022-2025 Electronic Arts, Inc. All rights reserved.
//Copyright (C) 2022 Electronic Arts, Inc. All rights reserved.
#pragma once

#include <array>
Expand Down
21 changes: 18 additions & 3 deletions include/fonttik/Fonttik.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include <filesystem>
#include <opencv2/core/mat.hpp>
namespace fs = std::filesystem;

#include "Results.h"
#include "../src/ColorblindFilters.hpp"

namespace tik
{
Expand All @@ -25,8 +26,18 @@ struct AsyncResults
fs::path pathToContrastResult;
fs::path pathToJSONSizeResult;
fs::path pathToJSONContrastResult;

fs::path pathToProtanResult;
fs::path pathToDeutanResult;
fs::path pathToTritanResult;
fs::path pathToGrayscaleResult;

bool overAllPassSize = true;
tik::ResultType overAllResultSize = PASS;
bool overAllPassContrast = true;
tik::ResultType overAllResultContrast = PASS;
std::vector<bool> overallPassColorblind = { true, true, true, true };
std::vector<ResultType> overallResultColorblind = { PASS, PASS, PASS, PASS };
};


Expand All @@ -44,12 +55,14 @@ class Fonttik

Results processMedia(Media& media);

std::pair<FrameResults, FrameResults> processFrame(Frame& frame, bool sizeByLine);

std::pair<FrameResults, FrameResults> processFrame(Frame& frame, std::vector<Frame> colorblindFrames, bool sizeByLine);
std::pair<fs::path, fs::path> saveResults(Media& media, Results& results);

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

ColorblindFilters* colorblindFilters = nullptr;

private:
bool setResolutionGuideline(const Media& media);

Expand All @@ -59,6 +72,8 @@ class Fonttik

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

std::vector<std::vector<TextBox>> createColorblindTextBoxes(std::vector<Frame> colorblindFrames, std::vector<TextBox> words);

/// <summary>
/// Sets the recognized text in the contrast results
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion include/fonttik/Frame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Frame {
static void paintTextBox(const int& x1, const int& y1, const int& x2, const int& y2, cv::Scalar& color, cv::Mat& image, int thickness = 1);

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

virtual ~Frame();

Expand Down
4 changes: 3 additions & 1 deletion include/fonttik/Media.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <opencv2/imgproc.hpp>
#include "Results.h"
#include "fonttik/Frame.hpp"
#include "../src/ColorblindFilters.hpp"

#include <rigtorp/SPSCQueue.h>
#include <vector>
Expand Down Expand Up @@ -42,7 +43,7 @@ class Media

//Factory Method that creates a video or an image depending on the file
//returns nullptr in case of invalid file
static Media* createMedia(std::string mediaSource);
static Media* createMedia(std::string mediaSource, ColorblindFilters* colorblindFilters=nullptr);

virtual void calculateMask(const MaskParams& maskParams);

Expand All @@ -56,6 +57,7 @@ class Media
/// Returns the current loaded frame pending to be analysed
/// </summary>
virtual Frame getFrame() = 0;
virtual std::vector<Frame> getColorblindFrames() = 0;

fs::path getPath() {
return fs::path{mediaSource};
Expand Down
Loading
Loading