You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在emu8086汇编中读取13h模式下的屏幕内容?

实现描摹对比与彩色像素检测的方案

首先得拆解你的核心需求:绘制参考图形(颜色A)→ 用户用颜色B描摹覆盖→ 检测剩余颜色A像素数量→ 基于覆盖率评分。下面分两种思路给你具体实现方案,不管你用Python、Unity还是网页开发栈,都能找到适配的方法:

一、直接检测屏幕彩色像素的方法

这种方法适合不需要精确控制画布的场景,直接读取指定区域的屏幕像素进行统计:

1. Python 快速原型实现

用pyautogui或Pillow库就能轻松完成屏幕抓取与像素统计:

import pyautogui
from PIL import Image

# 定义画布的坐标范围(避免统计屏幕其他区域)
canvas_x1, canvas_y1 = 100, 100  # 画布左上角坐标
canvas_x2, canvas_y2 = 800, 600  # 画布右下角坐标
canvas_region = (canvas_x1, canvas_y1, canvas_x2 - canvas_x1, canvas_y2 - canvas_y1)

# 抓取画布区域截图
screenshot = pyautogui.screenshot(region=canvas_region)

# 定义颜色A的RGB值(示例为纯红色)
color_a = (255, 0, 0)
remaining_a_count = 0
width, height = screenshot.size

# 遍历像素统计(添加容差避免颜色偏差)
for x in range(width):
    for y in range(height):
        r, g, b = screenshot.getpixel((x, y))
        if abs(r - color_a[0]) < 10 and abs(g - color_a[1]) < 10 and abs(b - color_a[2]) < 10:
            remaining_a_count += 1

print(f"剩余未覆盖的颜色A像素数:{remaining_a_count}")
# 假设你提前知道原始颜色A总像素数,直接计算评分
original_a_count = 50000  # 示例值,可通过提前统计参考图获取
score = ((original_a_count - remaining_a_count) / original_a_count) * 100
print(f"用户描摹评分:{score:.2f}分")

提示:高DPI屏幕下注意坐标缩放问题,pyautogui默认会适配,但手动计算坐标时要提前做转换。

2. Unity 游戏场景实现

在Unity里可以直接读取画布的RenderTexture或Texture2D像素,精度更高:

using UnityEngine;

public class TraceScoreCalculator : MonoBehaviour
{
    public Texture2D referenceImage; // 预先生成的颜色A参考图
    public RenderTexture canvasRenderTex; // 用户描摹的画布RenderTexture

    public void CalculateScore()
    {
        // 从RenderTexture读取像素数据
        Texture2D canvasTex = new Texture2D(canvasRenderTex.width, canvasRenderTex.height);
        RenderTexture.active = canvasRenderTex;
        canvasTex.ReadPixels(new Rect(0, 0, canvasRenderTex.width, canvasRenderTex.height), 0, 0);
        canvasTex.Apply();

        Color colorA = referenceImage.GetPixel(0, 0); // 取参考图第一个像素作为颜色A基准
        int originalACount = 0;
        int remainingACount = 0;

        // 遍历参考图和画布的对应像素
        for (int x = 0; x < referenceImage.width; x++)
        {
            for (int y = 0; y < referenceImage.height; y++)
            {
                Color refPixel = referenceImage.GetPixel(x, y);
                if (ColorUtility.AreColorsClose(refPixel, colorA, 0.1f))
                {
                    originalACount++;
                    // 检查用户画布对应位置是否被颜色B覆盖
                    Color userPixel = canvasTex.GetPixel(x, y);
                    // 这里假设颜色B是纯绿色,同样加容差判断
                    if (!ColorUtility.AreColorsClose(userPixel, Color.green, 0.1f))
                    {
                        remainingACount++;
                    }
                }
            }
        }

        float score = ((float)(originalACount - remainingACount) / originalACount) * 100;
        Debug.Log($"用户描摹评分:{score:F2}分");
    }
}

Unity自带的ColorUtility.AreColorsClose可以帮你轻松处理颜色容差,完美应对抗锯齿或绘制误差。

二、更精准的内存级描摹对比方案(不依赖屏幕抓取)

如果担心屏幕抓取的性能或精度问题,推荐直接在内存中对比画布数据,完全不受屏幕状态影响:

1. HTML5+JS 网页场景实现

把颜色A的参考图放在底层Canvas,用户在顶层Canvas描摹,直接对比两个Canvas的像素数据:

// 获取页面上的参考画布和用户描摹画布
const refCanvas = document.getElementById('reference-canvas');
const userCanvas = document.getElementById('user-canvas');
const refCtx = refCanvas.getContext('2d');
const userCtx = userCanvas.getContext('2d');

function getTraceScore() {
    const refData = refCtx.getImageData(0, 0, refCanvas.width, refCanvas.height).data;
    const userData = userCtx.getImageData(0, 0, userCanvas.width, userCanvas.height).data;

    let originalACount = 0;
    let remainingACount = 0;

    // 遍历像素(每4个元素代表一个RGBA像素)
    for (let i = 0; i < refData.length; i += 4) {
        // 判断参考图当前像素是否为颜色A(示例为红色)
        const isColorA = refData[i] === 255 && refData[i+1] === 0 && refData[i+2] === 0;
        if (isColorA) {
            originalACount++;
            // 判断用户画布对应位置是否被颜色B(示例为绿色)覆盖
            const isCovered = userData[i] === 0 && userData[i+1] === 255 && userData[i+2] === 0;
            if (!isCovered) {
                remainingACount++;
            }
        }
    }

    const score = ((originalACount - remainingACount) / originalACount) * 100;
    alert(`你的描摹评分:${score.toFixed(2)}分`);
}

这种方法完全在内存中运算,不受窗口缩放、屏幕分辨率影响,是精度最高的方案。

2. 掩码式对比(性能优化方案)

预先为颜色A的图形生成一个像素掩码,记录所有颜色A像素的坐标位置。用户描摹时,每绘制一个颜色B像素就检查是否在掩码范围内,若是则标记为已覆盖。最后统计未覆盖的掩码像素数量即可。

这种方法不需要遍历所有画布像素,只跟踪掩码内的目标像素,性能远高于全量遍历,尤其适合大尺寸画布。

三、关键注意事项

  • 颜色容差:绝对的RGB值相等判断很容易出错,一定要给合理的容差范围(比如RGB各通道差值小于10),应对抗锯齿、绘制偏差等情况。
  • 区域限制:只统计画布范围内的像素,避免屏幕上的UI按钮、状态栏等无关元素干扰结果。
  • 性能优化:大画布场景下,全量像素遍历会比较慢,可以用分块处理、多线程(Python用multiprocessing,Unity用协程)来提升速度。

内容的提问来源于stack exchange,提问作者Armando Herrera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:20:08