吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4213|回复: 13
上一主题 下一主题
收起左侧

[Python 原创] 对于最近光棱幻影坦克的一个解码脚本(图片隐写)

[复制链接]
跳转到指定楼层
楼主
celeryfx 发表于 2025-8-5 15:37 回帖奖励
本帖最后由 celeryfx 于 2025-8-5 19:26 编辑

最近在qq聊天记录中看到一种棋盘格一样的图片,消息里说通过调整曝光对比度等可以还原出被隐藏的里图,遂来了兴趣查看具体的原理。

通过观察图片,表图和里图使用不同的棋盘条纹,如下图所示
可以发现,里图的坐标点为(x+y)mod 2 == 0

我们知道 每个像素可以使用rgb的三元组来表示,因此,只需要提取对应里图的像素点,再进行提亮操作即可。
于是乎我们得到里图如下

但是此时,图片存在很多空格,观察起来依然不是非常方便,因此我们可以使用临近像素平均值(不含黑色像素)来代替,以此获得更加接近原图的结果。

综上,编写的python脚本如下(其中临近像素坐标让ai帮忙写的)
脚本效果还不错,对于比较明显的都可以自动解码,有些分析不出来的也可手动指定每行的偏移量和每行被挖空的点的模数
[Python] 纯文本查看 复制代码
from PIL import Image
import itertools
from pathlib import Path
import posixpath
import sys


def detect_stripe_modulus(img: Image.Image, max_modulus=6, threshold=0.4):
    img = img.convert("L")
    pixels = img.load()
    height, width = img.size

    best_score = 0
    best_mod = 2
    best_xoff = 1

    for xoff in range(1, max_modulus + 1):
        for x_mod in range(2, max_modulus + 1):
            score = 0
            total = 0
            for y in range(0, height,6):
                for x in range(0, width,9):
                    if (x + y * xoff) % (x_mod) == 0:
                        if pixels[y, x] / 255 < threshold:
                            score += 1
                        total += 1
                    else:
                        if pixels[y, x] / 255 >= threshold:
                            score += 1
                        total += 1

            match_ratio = score / total
            print(xoff, x_mod, "match_ratio", score, match_ratio)
            if match_ratio > best_score:
                best_score = match_ratio
                best_mod = x_mod
                best_xoff = xoff
            if match_ratio == 1:
                break

    return best_mod, best_xoff


def get_circle_pixels(center_x, center_y, r, max_x, max_y):
    """
    使用中点圆算法生成圆环上的所有整数坐标点(去重)
    返回: set of (x, y) 整数坐标
    """
    points = set()
    x = 0
    y = int(r + 0.5)  # 转为整数
    p = 1 - y  # 判断下一个点位置的决策参数

    def add_symmetric_points(cx, cy, x, y):
        """添加8个对称点"""
        points.add((cx + x, cy + y))
        points.add((cx - x, cy + y))
        points.add((cx + x, cy - y))
        points.add((cx - x, cy - y))
        points.add((cx + y, cy + x))
        points.add((cx - y, cy + x))
        points.add((cx + y, cy - x))
        points.add((cx - y, cy - x))

    add_symmetric_points(center_x, center_y, x, y)

    while x < y:
        x += 1
        if p < 0:
            p += 2 * x + 1
        else:
            y -= 1
            p += 2 * (x - y) + 1
        add_symmetric_points(center_x, center_y, x, y)

    return set([p for p in points if 0 <= p[0] < max_x and 0 <= p[1] < max_y])


def decode(p, xoff=None, xmod=None):
    path = Path(p)
    lmax = 0
    ori = Image.open(path)
    new = Image.new(ori.mode, ori.size)
    pixels = new.load()
    print(xoff,xmod)
    if xmod is None or xoff is None:
        xmod, xoff = detect_stripe_modulus(ori)
    print("choice",xoff, xmod, ori.size)
    for y, x in itertools.product(*[range(r) for r in ori.size[::-1]]):
        if not (x + y * xoff) % (xmod) == 0:
            continue
        r, g, b = ori.getpixel((x, y))
        lmax = max(r, g, b, lmax)
    amp = 255 / lmax
    # amp = min(amp,6.5)
    print(lmax, amp)

    for y, x in itertools.product(*[range(r) for r in ori.size[::-1]]):
        if not (x + y * xoff) % (xmod) == 0:
            continue
        r, g, b = ori.getpixel((x, y))
        r *= amp
        g *= amp
        b *= amp
        if r > 255 or g > 255 or b > 255:
            print(r, g, b)
        pixel = (int(min(r, 255)), int(min(g, 255)), int(min(b, 255)))
        pixels[x, y] = pixel

    # byd临近像素填充
    for y, x in itertools.product(*[range(r) for r in ori.size[::-1]]):
        if (x + y * xoff) % (xmod) == 0:
            continue
        n = 0
        r, g, b = (0, 0, 0)
        radius = 1
        while n == 0:
            for rx, ry in get_circle_pixels(x, y, radius, ori.size[0], ori.size[1]):
                if not (rx + ry * xoff) % (xmod) == 0:
                    continue
                rr, gg, bb = new.getpixel((rx, ry))
                r += rr
                g += gg
                b += bb
                n += 1
            radius += 1
        pixels[x, y] = (r // n, g // n, b // n)

    new.save(
        path.parent / (posixpath.splitext(path.name)[0] + "_decoded.png"),
    )


if __name__ == "__main__":
    decode(
        sys.argv[1],
        int(sys.argv[2]) if len(sys.argv) == 4 else None,
        int(sys.argv[3]) if len(sys.argv) == 4 else None,
    )


726448fc1e178a82ea11b99fb003738da977e8a0_decoded.png (577.72 KB, 下载次数: 336)

里图

里图

726448fc1e178a82ea11b99fb003738da977e8a0.jpg (210.29 KB, 下载次数: 188)

表里图

表里图

免费评分

参与人数 2吾爱币 +8 热心值 +2 收起 理由
qck + 1 + 1 谢谢@Thanks!
hrh123 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
xiaokk211 发表于 2025-8-5 16:58
红警迷的路过
3#
shaokui123 发表于 2025-8-5 15:57
4#
gugouo163 发表于 2025-8-5 16:14
5#
doraitoronn 发表于 2025-8-5 16:34
还以为有游戏mod用
6#
fengzhongdexin 发表于 2025-8-5 16:40
doraitoronn 发表于 2025-8-5 16:34
还以为有游戏mod用

俺也一样
7#
diyizuijimo 发表于 2025-8-5 16:57
doraitoronn 发表于 2025-8-5 16:34
还以为有游戏mod用

俺也一样
8#
smallmouse228 发表于 2025-8-5 17:11
以为红警,这标题可以呀!!
9#
Mr.Lemon 发表于 2025-8-5 17:33
这是以前贴吧玩的幻影坦克?
10#
xxkz 发表于 2025-8-5 17:41
看了半天,以为是红警,结果啥都不是
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-2-20 11:20

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表