11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ネタ記事】Akamai x UNIQLOのコラボTシャツに書いているコードをJavaでOCRして解読してみる

Last updated at Posted at 2025-07-15

このページについて

UNIQLOのチャリティTシャツプロジェクト「PEACE FOR ALL」でAkamaiとのコラボTシャツが発売されていた。
そして、そのコラボTシャツにbashスクリプトがデザインされていてどのような意味を持つのか気になったので調べてみた。

Tシャツはこちら ↓

※ 実は今回のコラボは2回目であり、コラボ1回目のTシャツは、安野たかひろさんが愛用されているとある界隈で(?)話題になっていた。直近のYoutubeでも着用されていた
ちなみに、コラボ1回目のTシャツはこちら。 

AkamaiはCDNで有名であるが、CDNだけではなくサイバーセキュリティやクラウドコンピューティングを提供する国際的な企業

https://www.akamai.com/ja/why-akamai

Tシャツのプリントを見てみる

Tシャツを見てみると、長い文字列が書いてありそれをbase64でデコードしてからevalで評価しているようだった。 
つまり長い文字列は、シェルスクリプトがbash64でエンコードものっぽい。

全て目視確認は流石に時間がかかるのでJavaでOCRをしてみる

  • なぜJavaでOCRをするのか?
    → OCRというとPythonのイメージが強かったので、あ、え、て、Javaでやってみようと思った

  • 利用するライブラリは?
    → Googleが開発しているOSSのTesseractというOCRエンジンをラップしたTess4Jを利用する

まずはプロジェクトを作成する

$ mvn -B archetype:generate \
  -DgroupId=com.example.ocr \
  -DartifactId=ocr-demo \
  -DarchetypeArtifactId=maven-archetype-quickstart

tesseractをインストール

Tess4Jは、tesseractをラップしたものになるので、tesseractが必要になるのでインストールする

$ brew install tesseract
$ brew install tesseract-lang

OCRする画像(Tシャツの画像)をresourcesに格納

↓ ディレクトリの構造は以下のようになる

$ tree                                                                                 
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── ocr
    │   │               └── App.java
    │   └── resources
    │       └── imgs
    │           └── akamai.jpg
    └── test
        └── java
            └── com
                └── example
                    └── ocr
                        └── AppTest.java
pom.xml
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example.ocr</groupId>
    <artifactId>ocr-demo</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>ocr-demo</name>
    <dependencies>
        <dependency>
            <groupId>net.sourceforge.tess4j</groupId>
            <artifactId>tess4j</artifactId>
            <version>5.16.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <mainClass>com.example.ocr.App</mainClass>
                    <systemProperties>
                        <systemProperty>
                            <key>jna.library.path</key>
                            <value>/opt/homebrew/lib</value>
                        </systemProperty>
                    </systemProperties>
                </configuration>
            </plugin>
        </plugins>

        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

App.java
package com.example.ocr;

import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;

import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;

public class App {
    public static void main(String[] args) {
        try {
            URL resourceUrl = App.class.getResource("/imgs/akamai.jpg");
            if (resourceUrl == null) {
                System.err.println("エラー: 画像ファイルが見つかりません。");
                return;
            }

            File imageFile = new File(resourceUrl.toURI());
            ITesseract instance = new Tesseract();
            instance.setDatapath("/usr/local/share/tessdata");
            instance.setLanguage("eng");
            instance.setVariable("user_defined_dpi", "500");
            instance.setOcrEngineMode(1);
            String result = instance.doOCR(imageFile);
            System.out.println("--- OCR結果 ---");
            System.out.println(result);
            System.out.println("---------------");

        } catch (TesseractException | URISyntaxException e) {
            System.err.println("OCR処理中にエラーが発生しました: " + e.getMessage());
        }
    }
}

実行してみる

実行結果は、ところどころ読めていない。
改善点としては、、、

  • 読み込む画像の文字を水平にしたりTシャツの歪みをなくす
  • 画質を上げる
  • グレースケールにする
$ mvn compile exec:java     
--- OCR結果 ---
GABIRIBSSH] eval "$(base64 -d <<< ‘TyEvY¥mluL2Jhe2gKCiMgQ29uZ3Jhd
HVsYXRpb25zTSBZ7b3UgZm91bmagdGh11GVhc3R1ciB1Z2chIOKdp0+4jwojLOOB3ub
Cge0Bp+0Bq00Bhu0B100B1uDBhOOBVuOBme+8gemac00Ble0C jOOBN+OCteOD1+00
ge0CpOOCuuOCKUimi+0BpOOBkeOBVUOB1+0Bn++8geKdp0+4jwokTyBEZWZpbmUgd
Gh THR1eHQgd68qYWSpbWF@Z0p@ZXhOBSLimaVORUFDReKZpUZPUUKZPUFMTOKZPV
BFOUNF4pm1Rk9S4pm1QUxM4pm1UEVBQQXimaVGT1LimaVBTEzimaVQRUFDReKZpUZ
PUUKZpUFMTOKZpVBFQUNF4pm1Rk9S4pm1QUxM4pm1IgoKIyBHZXQgdGV ybWLUYWwg
761tZW5zaW9ucwpjb2xzPSQodHB1dCBjb2xzKQpsaW51¢z0kKHRwdXQgbG1uZXMpC
gojTENhbGN1bGF@ZSB@aGUgbGVUuZ3RoIGOmIHRoZSBOZXh@CNR1eHRFGVUZSROPS
R7I3R1eHROCgojTEhpZGUgdGh1IGN1enNvegp@cHV@IGNpdm1zCgoj FRY XAgQIRS
TCtDIHRVIHNob3cgdGh1IGN1cnNveiBiZWZvemUgZXhpdGluZwp@cmFwICJecHVeL
GNub3JtOyBleG1@1i BTSUdJT1QKGiMgU2V@IGZyZXF1ZW5jeSBzY2FsawWSnIGZhY3R
vegpmemVxPTAUMgoK IyBJbmZpbm1@ZSBsb29wIGZvciBjb250aW51b3VzIGFuaWiIhd
Glvbgpmb3IgkCggdDewOyA7IHOrPTEgKSk7IGRVCiAGICAJIEV4dHJhYSQgb2511GN
oYXJhY3R1ciBhdCBhIHRpbWUKICAGIGNoYXI9TiR7dGV4dDpe@LCUgdGV4dF9sZWsnd
Gg6MX@iCiAgICAKICAGICMgQ2EsY3VsYXRLIHROZSBhbmdsZSBpbiByYWRpYWSzC1A
gICBhbmdsZT@kKGVjaG8gligkdCkgkiAkZnJlcSIgfCBiYyAtbCkKCiAgICAJIENNb
GN1bGF@ZSB@aGUgc21uZSBVZiB@aGUgYW5nbGUKICAgIHNpbmvfdmFsdWU9JCh1Y2
hvICJzKCRhbmdsZSkiIHwgYmMgLWwpCgogICAglyBDYWxjdWxhdGUgeCBwb3NpdGl
vbiB1c21uZyB@aGUgc21uZSB2YWx1ZQogICAgeDOkKGVjaG8gligkY29scyAvIDIpIC
sgKCRjb2xzIC8gNCkgkiAkc21uZV92YWx1ZSIgfCBiY yAtbCkKICAgIHg9JChwem1u
dGYgIiUuMGYiICIkeCIpCgogICAglyBFbnNicmUgeCBpcyB3aXRoaW4gdGVybW1uY
WwgYm91bmRzCiAgICBpZiAoKCB4IDwgMCApKTsgdGhlbiB4PTA7IGZpCiAgICBpZ1i
AoKCB4ID49IGNVbHMgKSk7IHRoZW4geD@kKChjb2xzIC@gMSkpOyBmaQoKICAgICM
gQ2FsY3VsYXRLIGNVbG9yIGdyYWRpZW5@1GJ1dHd1ZW4gMTIgKGNSYW4pIGFuZCAyM
DagkG9yYW5nZSkKICAGIGNVbG9yX3NBY XJ@PTEyCi AgICBjb2xvel91bmQ9MjA4CLA
St eee
Peroni oe es NAICS Ne ee eed
Wee ca sk ec ee eke Mao et
SSae gICy a6 OBWSLICJcMDMZWzM40z2U7JHtjb2xvenit1ia
gpLiRjaGFyXDAZM1swbSIKCiAgICAjIExpbmUgZmV1ZCB@b
yBtb3Z1IGRvd253Y XJkCiAgICB1Y2hvICIiCgpkb251Cgo= ')" PEACENFORBALE

グレースケール化してからOCRしてみる

  • 元画像
  • ↑を適当にこれでグレースケールにする
↑をOCRしてみた結果
G#i/binybashi eval "S$(base64 -d <<< TyEvYmluL 2Jhe2gkCiMgQ29uZ3Jhd
HVsYXRpb25zTSBZb3UgZm91bmagdGh1IGVhc3R1ciB1Z2chIOKdpO+4jwoj TOOBIN
Cge0Bp+0Bq00Bhu0B100B1UOBhOOBVUOBMe+8gemao00B1Le0C jOOBN+0CteODN+0H
ge0Cp00CuUOCKuimi+0BpOOBkeOBVUOB1+0Bn++8geKdpO+4jwokTyBEZWZpbmUg¢
Gh THR1eHQgdG8gYWSpbWFGZQp@ZXh@PSLimaVQRUFDReKZPUZPUUKZPUFMTOKZPY
BFOUNF4pm1Rk9S4pm1QUxM4pm1UEVBQ@XimaVGT1LimaVBTEzimaVQRUFDReKZpUZ
PUUKZpUFMTOKZpVBFQUNF4pm1Rk9S4pm1QUxM4pm1IgokIyBHZXQgdGVybW1uYWwg
7G1tZWSzaW9ucwpjb2xzPSQodHB1dCBjb2xzKapsaW51cz@kKHRwdXQgbG1uZXMpC
goj IENHbGN1bGF@ZSBGaGUgbGVUZ3ROIGOMIHROZSBEZXhE@CNRLEHRFbGVUZSROPS
R7I3R1eHRICGO}TEhpZGUgdGhLIGN1cnNvcgp@cHVELGNpdm1zCgojIFRyYXAGQIRS
TCLDIHRVIHNob3cgdGhLIGNIcnNvciBiZWZvcmUgZXhpdGluZwpe@cmFwICJ@cHVel
GNub3Jt0yBleG161iBTSUdJT1QKCiMgU2V@IGZyZXF 1ZW5jeSBzY2FsaWSnIGZhY3R
vegpmemVxPTAUMgoK lyBJbmZpbm1@ZSBsb29wIGZvciBjb258aW51b3VzIGFuaWihd
Glvbapmb3IgkCggdDewOyA7IHOrPTEgKSk7IGRVCiAGICAJIEV4dHJhY3Qgb25116N
oYXJhY3R1ciBhdCBhIHRpbWUKICAGIGNoYXI9IiR7dGV4dDpeTCUgdGV4dF9sZWs5nd
Gg6MX@iCi AGICAKICAGICMgQ2FsY3VsY XRLIHROZSBhbmdsZSBpbiByYWRpYWSzCiA
gICBhbmdsZT@kKGVjaG8gligkdCkgKiAkZnJ1cSIgfCBiYyAtbCkKCiAgICAjIENNb
GN1bGF@ZSB@aGUgc21uZSBVZiBaGUgYWSnbGUKICAgIHNpbmV fdmFsdWU9JCh1Y2
hvICUZKCRhbmdsZSki LHwgYmMgLWwpCgogICAglyBDYWxjdWxhdGUgeCBwb3NpdGl
vbiB1c21uZyB@aGUge21uZSB2YWx 1ZQogICAgeDOkKGV jaG8gligkY29scyAvIDIpIC
sgkCRjb2xzIC8gNCkgKiAkc2 1uZV92YWx 1ZSIgfCBiY yAtbCkKICAgIHg9JChwemlu
dGYgI iUuMGYiICIkeCIpCgogICAgIyBFbnNicmUgeCBpcyB3aXRoaW4gdGVybWluY
WwgYm91bmRzCi AgICBpZiAoKCB4IDwgMCApKTsgdGh1biB4PTA7IGZpCiAgICBpZi
AoKCB4ID49IGNvbHMgKSk7 IHRoZW4geD@kKChjb2xzICOgMSkpOyBmaQoKICAgICM
gQ2FsY3VsYXRLIGNVbG9yIGdyYWRpZW5@IGJ1dHd1ZW4gMTIgKGN5YW4pIGFuZCAyM
DagKG9yYW5nZSKKICAGIGNVbG9yX3NBY XJ@PTEyCiAgICBjb2xvcl91bmQOMjA4CiA
GICBjb2xvel9yYW5nZTAkKChjb2xvc191bmgLSBjb2xvcl9zdGFydCkpCiAgICB 3D
Rae AAI I AIUANEAN LC Ia nile eR
yYW5nZSkpCgogICAglyBQcmludCB@aGUgY 2hhemF jdGVyIHdpdGggMjU2L
WNvbG9yIHNIcHBvcnQKICAGIGV jaG8gLW51ICJcMDMzW2M40zZU7JHtjb2xven1tIiQ
odHB1dCBjdXAgJHQgJHgpliRjaGFyXDAzM1swbSIKCiAgICAJIExpbmUgZmV1ZCBab
yBtb3Z1IGRvd253Y XJkCiAgICB1Y2hvICIiCgpkb251Cgo= ')" PEACE FOR ALL
↑をOCRしてみた結果
GUNN «eval “S(base64 -d <<< ‘TyEv¥mluL2Uhe2gkCiMgQ29uZ3Jhd
HVsYXRpb25zTSBZb3UgZm9bmAgdGh1.IGVhc3R1ciB1Z2chTOKdpO+4jwoJTOOB1uo
Cge0Bp+0Bq00Bhu0B100B1u0BhOOBVuOBme+8gemac00B1e0C jOOBn+OCteOD1+0D
ge0CpOOCuUuOCKuimi+OBpOOBkeOBVUOB]+0Bn++8geKdp0+4jwoKIyBEZWZpbmUgd
Gh THR1eHOgdG8gYW5pbWFOZOP@ZXhOl"SLimaVORUFDReKZpUZPUUKZPUFMTOKZPV
BFOUNF4pm1Rk9S4pm1QUxM4pm1UEVBQOXimaVGT1LimaVBTEzimaVQRUFDReKZpUZ
PUUKZpUFMTOKZpVBFQUNF4pm1Rk9S4pm1QUxM4pm1IgoKIyBHZXQgdGV ybWLUYWwg
7G1tZWSzaW9ucwpjb2xzPSQodHB1dCBjb2xzKOpsaW51¢z@kKHRwdXQgbG1luZXMpC
gojT§NhbGN1bGFOZSB@aGUgbGVuZ3RoIGOmIHRoZSB@ZXh@CNR1eHRFbGVUZSROPS
R7I3R1eHROCgojTEhpZGUgdGhLIGN1cnNvegp@cHVEIGNpdm1zCgoj IFRYY X—gQ1RS
TCtDIHRVIHNob3cgdGh1IGNIcnNveiBiZWZvcemUgZXhpdGluZwp@cmFwICJecHVeL
GNub3JtO0yBleG16IiBTSUdJT1QK—i MgU2V@IGZyZXF 1ZW5jeSBzY2FsaWSnIGZhY3R
vegpmemVxPTAUMgoK IyBJbmZpbm1@ZSBsb29wIGZvciBjb250aW51b3VzIGFuaW thd
Glvbgpmb3IgkCggdDewOyA7IHOrPTEgKSk7IGRVCLAGICAJIBV4dHJHYSQgb251 IGN
oYXJhY3R1ciBhdCBhIHRpbWUKICAGIGNoYXI9TiR7dGV4dDpeICUgdGV4dF9sZWSnd
Gg6MX@iCi AGICAKICAgICMgQ2fsY3VsYXR1IHROZSBhbmdsZSBpbiByYWRPYWS5zCiA
gICBhbmdsZT@kKGVjaG8gligkdCkgKiAkZnJ1lcSIgfCBiYyAtbCkKCiAgICAJIENNb
GN1bGF@ZSBeaGUgc21UZSBVvZiB@aGUgYWSnbGUKICAgIHNpbmVfdmFsdWU9JChlY2
hvICJzKCRhbmdsZSkiIHwgYmMgLWwpCgogICAglyBDYWxjdWxhdGUgeCBwb3NpdG1
vbiB1c21uZyBHaGUge21uZSB2YWx1ZQogICAgeDOkKGVjaG8gligkY29scyAVIDIpIC
SQKCRjb2xzIC8gNCkgKiAke21uZV92YWx 1ZSIgfCBiYyAtbCkKICAgIHg9JChwemlu
dGYglivuMGYiICIkeCIpCgogICAglyBFbnNicmUgeCBpcyB3aXBoaW4gdGVybW1uY
WwoYm91bmRzCiAgICBpZiAOKCB4IDwgMCApKTsgdGhlbiB4PTA7IGZpCiAgICBpZi
AOKCB4ID49IGNvbHMgKSk7IHRoZW4geD@kKChjb2xzIC@gMSkpOyBmaQoKICAgICM
gQ2FsY3VsYXRLIGNVbG9yIGdyYWRpZW501GJ1dHd1ZW4gMTIgKGNSYW4pIGFuZCAyM
DggkKG9yYW5nZSkKICRgIGNvbG9yX3N@Y XJEPTEyCiAgICBjb2xvcl9lbmQ9MjA4CiA
GICBjb2xvcl9yYW5nZT@kKChjb2xvc191bmQgLSBjb2xvcl9zdGFydCkpCiAgICBjb
2xvcj@kKChjb2xvcl9zdGFydCArIChjb2xvcl9yYW5nZSAqIHQgByBsaWslcykgJSBj
b2xvcl9yYW5nZSkpCgogICAglyBQcmludCB@aGUgY2hhemF jdGVyIHdpdGggMjU2L
WNvbG9yTHN1cHBvcnQKICAgIGV jaG8gkW51ICJcMDMZzWz2M40zZU7JHt jb2xven1tliQ
odHB1dCBjdXAgJHQgJHgplikjaGFyXDAzM1swbSIKCiAgICAj IExpbmUgZmV1ZCB@b
yBtb3Z1IGRvd253YXJkCiAgICB1Y2hvICTiCgpkb251Cgo= ')"

結果

目視を利用しながら、OCRをした結果は以下のような結果になった
長すぎて諦めた

調べていたら、↓の記事が出てきた
ユニクロとAkamaiのコラボTシャツに書かれているコードを解読してみる。base64でデコードするとbashのシェルスクリプトが出てきて実行すると♥PEACE♥FOR♥ALL♥FOR♥ALL♥PEACE♥FOR♥ALL♥という文字が色付きで正弦波で流れた。

どうやら、↑に記載がありましたが、↓のようなシェルがencodeされていたみたい

#!/bin/bash

# Congratulations! You found the easter egg! ❤️
# おめでとうございます!隠されたサプライズを見つけました!❤️

# Define the text to animate
text="♥PEACE♥FOR♥ALL♥PEACE♥ FOR♥ALL♥PEACE♥FOR♥ALL♥"

# Get terminal dimensions
cols=$(tput cols)
lines=$(tput lines)

# Calculate the length of the text
text_length=${#text}

# Hide the cursor
tput civis

# Trap CTRL+C to show the cursor before exiting
trap "tput cnorm; exit" SIGINT

# Set freqeency scaling factor
freq=0.2

# Infinite loop for contineous aniiation
for (( t=0; ; t+=1 )); do

    # Extract one character at a time
    char="${text:t % text_length:1}"
   
    # Calculate the angle in radians
    angle=$(echo "($t) * $freq" | bc -l)

    # Calculate the sine of the angle
    sine_value=$(echo "s($angle)" | bc -l)

    # Calculate x position using the sine value
    x=$(echo "($cols / 2) + ($cols / 4) * $sine_value" | bc -l)
    x=$(printf "%.0f" "$x")

    # Ensure x is within terminal bounds
    if (( x < 0 )); then x=0; fi
    if (( x >= cols )); then x=$((cols - 1)); fi
    # Calculate color gradient between 12 (cyan) and 208 (orange)
    color_start=12
    color_end=208
    color_range=$((color_end - color_start))
    color=$((color_start + (color_range * t / lines) % color_range))
    # Print the character with 256-color support
    echo -ne "\033[38;5;${color}m"$(tput cup $t $x)"$char\033[0m"

    # Line feed to move downward
    echo ""
   
done

実行してみると、、↓ 「♥PEACE♥FOR♥ALL♥PEACE♥ FOR♥ALL♥PEACE♥FOR♥ALL♥」の文字列が波で出てきた

参考

11
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?