AI 이미지의 글자, 숫자, 화살표가 맞는지 확인하기

AI로 만든 설명 이미지를 쓰기 전에는 글자와 숫자, 화살표를 하나씩 확인하세요. 숫자는 맞아도 ‘제외’가 ‘포함’으로 바뀌거나 화살표가 반대로 이어지면 설명의 뜻이 달라집니다.

먼저 이미지에 들어가야 할 문구와 숫자, 연결 방향을 짧게 적습니다. 그다음 원본을 크게 보고, 실제 사용할 크기로 줄이거나 일부를 잘랐을 때도 중요한 내용이 보이는지 확인합니다.

아래의 “보임·읽힘” 값은 검증기 시험용 합성 입력입니다. Python 예제는 정상·오류 전사 자료의 조건을 대조하며, 이미지 픽셀이나 OCR 인식 결과를 검사하는 코드는 아닙니다.

접수 12건에서 보류 3건을 제외해 승인 9건을 남기는 세로 3단계 설명용 도해. 두 아래 화살표와 12 - 3 = 9, 자동 발행 안 함을 표시한 가상 업무 계약
설명용 도해: 가상 3단계 정답 계약이다. 본문의 검증 예제는 사람이 작성한 합성 전사를 대조한 것이며 OCR·이미지 픽셀 인식·새 AI 이미지 성능 실험이 아니다.

도식을 만들기 전에 글자와 관계의 정답을 적기

OpenAI 이미지 생성 안내의 제한 사항은 정밀한 문자 배치·명료성, 구조화된 배치 제어에 어려움이 남을 수 있다고 설명합니다. 이 내용은 특정 이미지가 실제로 틀렸다는 증거가 아닙니다. 아래 계약은 제작 결과를 확인하기 위해 이 글에서 정한 기준입니다.

가상 입력은 접수 12건 중 보류 3건을 제외해 승인 9건을 남기는 업무입니다. 승인 건수가 정해졌다고 자동으로 발행하지는 않습니다. “자동 발행 안 함”을 별도 고정 문구로 넣습니다. 실제 접수·승인·발행 기록은 아닙니다.

계약 항목 고정 정답 바뀌면 문제인 이유
1단계 N1 접수 12건 입력 수량과 대상이 달라짐
2단계 N2 보류 3건 제외 보류를 승인에 포함시키지 않아야 함
3단계 N3 승인 9건 출력 수량이 달라짐
연산 12 - 3 = 9 제외의 연산은 더하기가 아님
정책 자동 발행 안 함 부정이 빠지면 실행 의미가 바뀜
연결 1 N1 → N2 접수에서 보류 분리로 진행
연결 2 N2 → N3 보류를 뺀 결과만 승인 단계로 전달
금지 연결 보류 3건을 발행으로 연결하지 않음 보류 대상이 출력에 섞이지 않도록 함

노드 이름 N1·N2·N3는 검수 기록의 식별자입니다. 이미지에 반드시 작은 코드까지 넣어야 한다는 뜻은 아닙니다. 한글 문구와 숫자·관계는 사람이 알아볼 수 있어야 합니다. ASCII 하이픈을 빼기 부호로 쓰는 고정 식이며 다른 모양의 부호를 허용하려면 계약을 먼저 바꾸고 그 사유를 기록합니다.

원본과 대표 크롭과 축소를 별도 항목으로 두기

원본을 통과시킨 뒤 썸네일도 통과했다고 복사하지 않습니다. 크롭은 일부를 제거하고 축소는 글자를 작게 만들므로 실패 이유가 다릅니다. 아래 크기는 예제 제작·검수 계획이며 실제 이미지 파일을 이 크기로 잘라 시험했다는 기록이 아닙니다.

보기 ID 계획한 보기 직접 확인할 조건
original 1200×675, 16:9 원본 고정 문자·숫자·연산·부정·두 화살표 전부 대조
center_crop 원본 중앙의 대표 1:1 크롭, 675×675 모든 필수 문구·화살표가 잘리지 않고 보이는지
half_size 원본을 약 절반으로 표시, 600×338 확대하지 않은 표시 크기에서 부정과 숫자를 읽을 수 있는지

이 계획에서는 필수 요소를 원본의 중앙 정사각형 안에 배치합니다. 그래도 실제 크롭의 위치와 웹페이지 표시 방식이 다르면 다시 확인해야 합니다. half_size의 높이는 337.5를 반올림한 계획값이며 검수기에서 이미지 리샘플링을 수행하지 않습니다.

검토자는 원본 파일 식별자와 해당 보기의 파일·표시 크기를 먼저 기록합니다. 같은 이름으로 다른 버전의 그림을 확인하면 전사가 정확해도 결과에 연결할 수 없습니다. 실제 작업에서는 이미지 버전과 해시 또는 변경 이력이 있는 파일 식별자를 함께 남기고 최종 페이지의 표시 크기로 확인합니다.

일부러 틀린 전사로 검사 항목을 확인하기

다음은 이미지에서 읽어 낸 관측이 아닙니다. 사람이 검수기 시험용으로 오류를 작성했습니다. original 사본에는 여러 오류를 함께 넣고, center_crop과 half_size는 원본 사본과 별도로 잘림·읽기 실패를 표시했습니다.

합성 오류 정답과 달라진 것 검사 항목
보류 3건 포함 제외가 포함으로 바뀜 고정 문자
승인 숫자를 8로 기록 12 - 3과 결과가 불일치 숫자·독립 산술
12 + 3 = 9 연산 부호와 식이 틀림 고정 연산
자동 발행 함 안이 빠져 정책이 반대로 바뀜 부정 표현
N2 → N1 접수와 보류 분리 관계가 반대 화살표 관계
보류를 발행으로 연결 제외 대상이 출력으로 이어짐 금지 연결
크롭의 N3 보임=false 승인 단계가 잘린 상황을 가정 필수 요소의 보임
축소본 정책 읽힘=false 부정 문구를 읽기 어려운 상황을 가정 필수 요소의 읽힘

숫자 검사에서는 전사 숫자와 정답 숫자를 대조하고, 접수−보류=승인도 별도로 계산합니다. 숫자 전사 세 개가 모두 일관되게 잘못된 경우에도 정답 계약과의 불일치를 잡아야 합니다. 문자 전사와 숫자 구조가 같은지, 실제 픽셀에서 무엇을 읽을 수 있는지는 사람이 확인해야 합니다.

전체 정답 대조 코드를 복사해 실행하기

아래를 check_image_contract.py로 저장한 뒤 python check_image_contract.py를 실행합니다. 계약·정상 전사·오류 전사가 전부 코드 안에 있습니다. 네트워크, 이미지 생성 모델, 이미지 파일, OCR 패키지가 필요 없습니다.

"""Compare human-authored synthetic transcripts, never pixels or OCR."""
import copy
CONTRACT = {
    'texts': {'N1':'접수 12건', 'N2':'보류 3건 제외', 'N3':'승인 9건'},
    'numbers': {'received':12, 'held':3, 'approved':9},
    'operation':'12 - 3 = 9', 'policy':'자동 발행 안 함',
    'edges':[('N1','N2'), ('N2','N3')], 'hold_to_publish':False,
    'views':['original','center_crop','half_size'],
}
REQUIRED = ['N1','N2','N3','operation','policy','arrows']
GOOD = {
    key: copy.deepcopy(value) for key,value in CONTRACT.items() if key != 'views'
}
GOOD['visible']={key:True for key in REQUIRED}
GOOD['readable']={key:True for key in REQUIRED}

def check_transcription(observed):
    errors = []
    texts = observed.get('texts', {})
    if set(texts) != set(CONTRACT['texts']):
        errors.append('NODE_SET')
    for key, expected in CONTRACT['texts'].items():
        if texts.get(key) != expected:
            errors.append('TEXT:' + key)
    numbers = observed.get('numbers', {})
    if (numbers != CONTRACT['numbers']
            or any(type(value) is not int for value in numbers.values())):
        errors.append('NUMBERS')
    if set(numbers) == set(CONTRACT['numbers']):
        if numbers['received'] - numbers['held'] != numbers['approved']:
            errors.append('ARITHMETIC')
    if observed.get('operation') != CONTRACT['operation']:
        errors.append('OPERATION')
    if observed.get('policy') != CONTRACT['policy']:
        errors.append('POLICY')
    edges = [tuple(edge) for edge in observed.get('edges', [])]
    if sorted(edges) != sorted(CONTRACT['edges']):
        errors.append('EDGES')
    if observed.get('hold_to_publish') is not False:
        errors.append('HOLD_CONNECTION')
    for key in REQUIRED:
        if observed.get('visible', {}).get(key) is not True:
            errors.append('NOT_VISIBLE:' + key)
        if observed.get('readable', {}).get(key) is not True:
            errors.append('NOT_READABLE:' + key)
    return errors

def check_views(views):
    return {
        name: check_transcription(views[name]) if name in views else ['VIEW_MISSING']
        for name in CONTRACT['views']
    }

def run_demo():
    views = {name:copy.deepcopy(GOOD) for name in CONTRACT['views']}
    normal = check_views(views)
    assert all(not result for result in normal.values())
    print('synthetic_transcripts_normal', normal)
    bad = copy.deepcopy(views)
    original = bad['original']
    original['texts']['N2'] = '보류 3건 포함'
    original['numbers']['approved'] = 8
    original['operation'] = '12 + 3 = 9'
    original['policy'] = '자동 발행 함'
    original['edges'] = [('N2','N1'), ('N2','N3')]
    original['hold_to_publish'] = True
    bad['center_crop']['visible']['N3'] = False
    bad['half_size']['readable']['policy'] = False
    failures = check_views(bad)
    assert failures['original'] == [
        'TEXT:N2','NUMBERS','ARITHMETIC','OPERATION','POLICY','EDGES','HOLD_CONNECTION'
    ]
    assert failures['center_crop'] == ['NOT_VISIBLE:N3']
    assert failures['half_size'] == ['NOT_READABLE:policy']
    print('synthetic_transcripts_bad', failures)
    recovered = copy.deepcopy(views)
    assert all(not result for result in check_views(recovered).values())
    assert bad['original']['policy'] == '자동 발행 함'
    print('synthetic_transcripts_recovery PASS; bad_transcripts_preserved=True')
    print('ocr_runs=0; actual_image_experiments=0; generated_images=0')

if __name__ == '__main__':
    run_demo()

visible과 readable은 실제 검토자가 각 보기를 본 뒤 채울 항목입니다. 여기서는 모두 합성 값으로 넣었습니다. 코드가 True라고 읽었다는 이유만으로 글자가 실제로 선명하다고 주장할 수 없습니다. 마찬가지로 전사의 edges는 검토자가 화살표의 시작·끝을 보고 적어야 하는 관계입니다.

이 작은 검사기는 정해진 자료형의 가상 입력을 전제로 합니다. 임의 JSON 전체의 스키마 검증, 모든 그림의 문자 인식, 객체 위치 판별을 구현하지 않습니다. 업무 자료에 적용하기 전에는 전사 필드 누락·잘못된 자료형과 검토자의 판독 불확실성도 보류로 처리해야 합니다.

로컬 실행에서 확인한 오류와 복구

정상 합성 전사는 세 보기 모두 통과했습니다. 오류 사본은 원본 항목에서 7개 사유, 대표 크롭에서 잘림 1개, 축소본에서 읽기 실패 1개를 돌려줬습니다. 이것은 생성 이미지의 오류율이 아니라 사람이 만든 반례를 정답표와 비교한 결과입니다.

synthetic_transcripts_normal {'original': [], 'center_crop': [], 'half_size': []}
synthetic_transcripts_bad {'original': ['TEXT:N2', 'NUMBERS', 'ARITHMETIC', 'OPERATION', 'POLICY', 'EDGES', 'HOLD_CONNECTION'], 'center_crop': ['NOT_VISIBLE:N3'], 'half_size': ['NOT_READABLE:policy']}
synthetic_transcripts_recovery PASS; bad_transcripts_preserved=True
ocr_runs=0; actual_image_experiments=0; generated_images=0

복구는 정상 계약에 맞는 새 전사 사본을 다시 비교한 것입니다. 실제 이미지를 수정·재생성하거나 잘림을 복구한 과정은 아닙니다. 오류 전사는 그대로 남겨 두었습니다. 실제 도식을 수정했다면 새 이미지의 원본·크롭·축소를 다시 보고 새 전사를 작성해야 합니다. 예전 전사에 오류 문구만 지우는 것으로 최종 이미지가 검증되지는 않습니다.

텍스트 대체 설명과 최종 기록 남기기

이미지에만 정답을 넣지 않습니다. 본문에도 계약 표와 흐름 설명을 남기면 글자 확대나 다른 읽기 방식을 사용하는 독자가 같은 내용을 확인할 수 있습니다. W3C 비텍스트 콘텐츠 안내는 비텍스트 콘텐츠에 목적을 전달하는 텍스트 대안을 제공하는 기준을 설명합니다. 이 글의 대체 설명을 붙였다는 사실만으로 전체 페이지가 접근성 기준을 충족했다고 단정하지 않습니다.

W3C 의미 있는 순서 안내는 순서가 의미에 영향을 줄 때 올바른 읽기 순서를 유지하는 기준을 설명합니다. 이 도식의 본문 설명은 접수, 보류 분리, 승인 순서를 그대로 따릅니다. 화살표를 색상만으로 구분하지 않고 시작과 도착 관계도 글로 설명합니다.

복사할 수 있는 대체 설명은 다음과 같습니다.

설명용 도해. 접수 12건에서 보류 3건을 제외해 승인 9건을 남긴다.
흐름은 접수 → 보류 분리 → 승인 순서이며 12 - 3 = 9이다.
보류 3건은 발행으로 연결하지 않고 자동 발행도 하지 않는다.
가상 업무 계약이며 실제 AI 이미지 성능이나 실행 기록이 아니다.

실제 검수 기록에는 다음 항목을 남깁니다.

계약 ID / 계약 버전 / 정답 원문:
이미지 파일 식별자 / 버전·해시 / 확인 시각:
보기: 원본 / 대표 크롭 / 실제 표시 크기의 축소
고정 문자 / 숫자 / 연산 / 부정 / 화살표 시작·끝:
필수 요소 보임 / 읽힘 / 판독 불확실:
보류 사유 / 수정 이미지 식별자 / 재검토자:
본문 정답표·대체 설명과 최종 이미지가 같은지:

정답 문구를 읽을 수 없거나 승인 단계가 잘리면 해당 보기는 보류합니다. 숫자와 한글이 맞아도 화살표가 틀리면 통과가 아닙니다. 이 체크는 가상 3단계 도식의 계약에 한정되며, 이미지 저작권·보안·의학·법률 내용의 정확성이나 모든 접근성 항목은 별도 검토가 필요합니다. 구조화된 결과를 먼저 계약으로 검산하는 방식은 업무용 AI JSON 계약, 사람 판단을 남기는 과정은 AI 결과 승인대장에서 이어 볼 수 있습니다.

작성자 소개