Checklist IOAI TST 2025 IOAI Team Selection Test · Task 1
Image Restoration
Identify which of 12 2x2 colour-channel filters was applied to an RGB image and reconstruct the original image.
The task
Each 128x128 RGB image has been passed through one of 12 colour filters of size 2x2. A filter is a list of four channel letters (for example ['R', 'G', 'B', 'R']) stating which single channel is kept at the top-left, top-right, bottom-left and bottom-right pixel of every 2x2 block; the other channels are set to 0. Every filter contains all three channels at least once and its repeated letter lies on a diagonal, which gives exactly 12 possible filters. The same filter is used over the whole image, and the statement includes reference code for applying it.
The contestant must determine which filter was applied and recover an approximation of the original image. Training data give filtered and original versions of the same images; the test set contains filtered images only.
Abridged and translated by SOTA from the official Russian materials. The official statement has the exact rules, and it wins wherever this summary differs.
In English
This task was published in Russian. SOTA translated its 2 files into English on 17 September 2026.
- Competition overview Russian original of Competition overview
- Data description Russian original of Data description
Read the competition overview in English
Image Restoration
English translation by SOTA – AI Community of the Russian original. Licensed MIT, like the original. Organisers who would like this translation removed can email [email protected].
Contest 1 (25 June 2025) of the Kazakhstan IOAI Team Selection Test (Отборочные на IOAI), 2025. This is the Overview tab of the Kaggle competition "Upsolving TST Day 1" (subtitle: "Up Solving for TST Day 1"), the host's public upsolving copy of the contest, open from 25 June to 1 September 2025. Original: kaggle.com/competitions/up-solving-tst-day-1. The Data tab is translated in a separate file.
Overview
Statement
You have an image of size 128×128 in RGB format (three channels). However, one of 12 colour filters of size 2×2 has been applied to it.
Each filter determines which channel (R, G or B) is kept in each of the 4 cells of a 2×2 block, and the other channels are zeroed. All the other pixels at these positions in the other channels are set to zero (become 0).
Task
You are given an image after the filter has been applied. It is known that the same filter was used over the whole image, but which one is unknown.
Your task is to:
- Determine which of the 12 possible filters was applied.
- Reconstruct an approximation of the original image.
💻 The starter notebook is available here: https://www.kaggle.com/code/akhanov/tst-day1-starter
Description
Filter properties:
-
A filter is a list of four symbols:
['R', 'G', 'B', 'R']. -
These symbols determine which channel is kept in the:
- top-left (0, 0),
- top-right (0, 1),
- bottom-left (1, 0),
- bottom-right (1, 1) pixels of a 2×2 block.
-
It is guaranteed that:
- The filter contains all three channels (R, G, B) at least once.
- Identical letters lie on a diagonal (either the main diagonal or the anti-diagonal).
- There are 12 possible filters in total that satisfy these conditions.
Filter example:
['R', 'G',
'B', 'R']
This means:
- Pixel (0,0) keeps only the red (R) channel.
- Pixel (0,1) keeps green (G).
- Pixel (1,0) keeps blue (B).
- Pixel (1,1) keeps red (R).
Applying the filter
The filter is applied to the whole image in 2×2 blocks, that is:
- (0,0)-(1,1), (0,2)-(1,3), ..., (126,126)-(127,127)
- The filter is applied with the same rules on every 2×2 block.
Example filtering code:
def apply_fast_filter(img, pattern):
"""Applies a 2x2 filter to an image."""
# Create a new image with the same dimensions
filtered_img = np.zeros_like(img)
# For each pixel in the 2x2 block, keep only the required channel
# Top left
filtered_img[0::2, 0::2, pattern[0]] = img[0::2, 0::2, pattern[0]]
# Top right
filtered_img[0::2, 1::2, pattern[1]] = img[0::2, 1::2, pattern[1]]
# Bottom left
filtered_img[1::2, 0::2, pattern[2]] = img[1::2, 0::2, pattern[2]]
# Bottom right
filtered_img[1::2, 1::2, pattern[3]] = img[1::2, 1::2, pattern[3]]
return filtered_img
Here pattern is a list of channel indices (0 — R, 1 — G, 2 — B), for example [0, 1, 1, 0] instead of ['R', 'G', 'G', 'R'].
Evaluation
📏 Metric
The metric in this task is PSNR (Peak Signal-to-Noise Ratio) between the reconstructed image and the original.
where:
Iis the original image (before the filter was applied),Îis the image reconstructed by the participant,H, W, Care the height, width and number of channels (in this task: 128×128×3),- All pixel values are from
0to255(typeuint8).
- All image values lie in the range from 0 to 255 (type
uint8).
The higher the PSNR value, the better the reconstruction quality.
Translated by SOTA. The Russian original is the official version and wins wherever the two differ. This translates the Overview and Data tabs of the host's public upsolving copy on Kaggle; the Rules tab (code of conduct, allowed websites and libraries) is not included. The host's starter notebook (in English) writes integer ids and columns named pixel_0, pixel_1, …, which differs from the sample_submission.csv layout described on the Data tab (ids such as img_01 and columns 0 to 49151). The competition data on Kaggle are licensed MIT. If you organise this olympiad and would like the translation removed, email [email protected] and we will take it down.
At a glance
- You get
- train/filtered/ and train/original/ (matching PNG file names); test/ with filtered PNG images only;
sample_submission.csv. - You submit
submission.csvwith one row per test image: id (file name without .png) and columns 0-49151 holding the restored pixel values (0-255) in the order of .reshape((128, 128, 3)).flatten(), channels in BGR order.- Scoring
- PSNR between the restored and original images: PSNR = 10 log10(255^2 / MSE), MSE over 128x128x3 uint8 values; higher is better. Contest scoring (hub page): each task is worth at most 100 points; Norm_Score = (Submission_Score - Min_Score) / (Max_Score - Min_Score) x 100, where Min_Score is the lower of 0.9 x baseline score and the lowest participant score, and Max_Score is the higher of 0.9 x the Scientific Committee solution score and the best participant score.
- Rules
- Read-only access to stackoverflow.com, scikit-learn.org, pytorch.org, huggingface.co, numpy.org, github.com, python.org, pypi.org, a search engine restricted to these sites and a translation site.
- GPT-4o (or a newer version announced before the contest) is allowed through the platform integration; other LLMs, chats, Copilot tools and APIs are forbidden unless the task says otherwise.
- Allowed libraries include torch, scikit-learn, xgboost, catboost, lightgbm, transformers, spacy, nltk, gensim, fasttext, pandas, numpy, scipy, opencv-python, Pillow, torchvision, scikit-image, matplotlib, seaborn, plotly and common utilities; TensorFlow and Keras are not available.
- Pre-trained models and external data are forbidden unless the task allows them; no extra training time after the contest ends; contestants may be asked to upload code, models and/or predictions.
- Format
- Kazakhstan IOAI Team Selection Test 2025, contest 1 of 4 (25 June 2025), run as a private Kaggle competition; the public Kaggle copy is an upsolving clone of it.