# 1st Place Solution

New Team Name - 1st Place Solution
Congratulations to all the other winners and thanks to Kaggle for hosting such a unique competition - it was a lot of fun to participate in! Thanks also to my teammates
[@huanligong](https://www.kaggle.com/huanligong)
and
[@kenyeungtech](https://www.kaggle.com/kenyeungtech)
!
TL;DR
The notebook for our top scoring submission can be found
[here](https://www.kaggle.com/code/conormacamhlaoibh/new-team-name-1st-place-solution)
.
Generate 64 baseline images with Segmind's SSD-1B model.
Convert each image to an SVG.
Add the OCR decoy, prompt text, and a number of other aesthetic artifacts to each SVG.
Convert the SVGs to images, apply the image processing pipeline, and calculate their aesthetic scores.
Select the SVG with the highest aesthetic score for submission.
OCR Exploits
Avoiding Hallucinations
We embed three visible characters in the top left corner of each SVG to avoid OCR hallucinations. Running a search across three-letter combinations of characters revealed that
"ZOK"
produced the highest average aesthetic scores without impacting VQA scores.
Hiding Additional Text
The most lightweight and reliable method of improving the VQA score is to directly include text related to the prompt in the image. However, simply embedding the prompt text would result in scores of zero due to the OCR penalties applied by the metric. To avoid these penalties, we hide any embedded text using the following repeating, noise-like pattern:
<defs>
    <pattern id x y width height patternUnits>
        <g opacity>
            <path fill d/>
            <path fill d/>
            <path fill d/>
            <path fill d/>
        </g>
    </pattern>
</defs>
<rect width height fill/>
This results in text which is hidden in both the raw and partially processed image (which is used for OCR). The fully processed image, which is used to calculate aesthetic and VQA scores, reveals the hidden text:
![Hidden Text](assets/f70789f2d2ed2375dff97373.png)
Image Generation and Conversion
Diffusion Model
We use
Segmind
's
[SSD-1B](https://huggingface.co/segmind/SSD-1B)
model to generate 64 images for the given description of the target SVG.
To improve efficiency, we apply the following modifications to the base model:
Replace the default VAE with
madebyollin
's
[Tiny AutoEncoder for Stable Diffusion (XL)](https://huggingface.co/madebyollin/taesdxl)
,
Use a DPM-Solver multistep scheduler with 12 inference steps,
Enable DeepCache with
cache_interval=2
and
cache_branch_id=0
,
Run image generation across both T4 GPUs in parallel, generating 32 images per GPU.
Each image is generated at a resolution of 384×384 with a guidance scale of 8. We use the following prompts:
Prompt
flat  illustration, flat  blocks, hard  boundaries, solid fills, clipart , \
no shading, no blending, minimalist, simple design, saturated colors, extremely simplistic  minimal, \
:  clip art, small   :  art of {SVG_DESCRIPTION}
Negative Prompt
photorealistic, realistic, detailed, D, complex shading, gradients, soft edges, , signature, \
watermark, texture, painting, blurry, pixelated, thin lines, dots, cropped ,  frame
With multi-threading, image generation takes ~15 seconds for 64 samples. However, due to the multi-threading bug currently present in Kaggle packages, we opted to use single-threading for more reliable submissions, resulting in a ~30 second generation time.
Conversion to SVG
Each image is downsampled and quantized to six colors. For each of the six colors, we extract contours using OpenCV and simplify them to polygons. We then scale the polygons back to their original size and convert them to compressed SVG paths. We rank each extracted path by its size, centrality and simplicity and then continuously add them to the SVG until the 6000-byte size limit is reached. This process takes ~2.5 seconds for a batch of 64 images.
Examples of Generated Images and Converted SVGs
![Generated Images and Converted SVGs](assets/b7bcf67040e7ebe6aec1947b.png)
Constructing the SVG
We scale the SVG we extracted from the generated image down to 40% of its original size and place it in the top center of our final SVG. We then add the anti-OCR hallucination text in the top left corner, remove all stopwords from the SVG description, and embed the text just below the image. The text is embedded using SVG paths which we also heavily compress.
Finally, we add a number of other artifacts to the SVG which are designed to improve the aesthetic score without negatively impacting the VQA score:
A 5×4 patch of colored squares (we test four different variations of these colored squares for each generated image),
Green text spelling
"KUZ"
,
Green text spelling
"3Q3"
,
Gray text spelling
"SSQ"
,
Green text spelling
"FRANCE XK ARTS"
(if sufficient space is available after the SVG description text).
Each of these artifacts was found using either a genetic algorithm, a hill climb search, or occasionally a manual guess and check approach.
Examples of Fully Constructed SVGs (before and after processing)
![Fully Constructed SVGs](assets/52532c4a14678bf1a6eb1f10.png)
Fallback SVGs
In case of timeouts or exceptions we also prepare a simple text-only SVG which includes anti-OCR hallucination text, the text from the SVG description with a simple suffix (
"AMAZING EUROPE OIL ART EUROPE"
) and a few of the aforementioned aesthetic artifacts.
We didn't spend too much time refining these fallback SVGs in the later stages of the competition as our highest scoring submissions didn't make any use of them.
![Fallback SVG](assets/54fc0ddb6bdda84e8091bf02.png)
Final SVG Selection
We convert each of the SVGs back to images and apply the image processing pipeline to them. We use a custom implementation of the image processor from the metric that is much more efficient and produces almost identical results. We then calculate the aesthetic score for each of the images and simply return the SVG that got the highest score. The average aesthetic score for our selected SVGs was ~0.563 and the VQA score was ~0.88 when run on the validation dataset in our highest scoring submission.
What Didn't Work
We experimented with many different techniques and variations on the above approach that didn't result in improved scores:
Incorporating CLIP scores, VQA scores, etc. into the equation we used to select the final SVG for submission.
Generating more than 64 images (although on the private LB this seemed to work quite well).
Calculating mean aesthetic scores for each SVG across multiple applications of the image processing pipeline.
Different placements of aesthetic patches of colored squares (along the border, to the left of the image, etc.).
Bonus: Old Metric Solution
For the old metric we used a differentiable approach to find a set of 237 small squares that produced the highest aesthetic score with some small text designed to maximize the VQA score. The following image got a score of 1.014 with an aesthetic score of >1.2:
![Old Metric](assets/543cc878eec88e0f34ef9f61.png)