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

OpenCV提取图像像素RGB值 按区域迁移颜色到另一图像问题排查

按区域提取图像RGB值迁移至第二幅图像实现方案

需求说明

  • 实现功能:从第一幅图像中提取单个像素的RGB颜色值,按对应区域匹配关系将颜色迁移到第二幅图像。已掌握图像颜色通道提取基础方法,但多次调试未得到预期结果。

已尝试方案与问题

方案1:形态学处理后做图像减法

实现逻辑:先对原始彩色图像做腐蚀操作消除黑色轮廓,提取颜色像素后,将第二幅图像与处理后的第一幅图像做减法,期望残差为带颜色的轮廓,代码运行时抛出错误。
对应实现代码:

import cv2
import numpy as np 
import os
import matplotlib.pyplot as plt
from natsort import natsorted
os.chdir('/kaggle/input/maskedoutput')
stroke_list = natsorted(os.listdir())

for i,v in enumerate(stroke_list):
    image = cv2.imread(v, cv2.IMREAD_UNCHANGED)
    
    if image.shape[2] == 4:    
          a1 = ~image[:,:,3]  
          image = cv2.add(cv2.merge([a1,a1,a1,a1]), image)   
          image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
    else:
        image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
    plt.imshow((image))
    plt.show()
    copy = image.copy()

    kernel = np.ones((15,15), np.uint8)
    closing = cv2.morphologyEx(copy, cv2.MORPH_CLOSE, kernel)
    img_erode = cv2.erode(closing, kernel, iterations=1)# 消除黑色轮廓
    height, width, channel = img_erode.shape
    
    for x1 in range(0,width):
        for y1 in range(0,height):
            channels_x1y1 = img_erode[y1,x1]
            
    os.chdir('/kaggle/input/maskstrokes')
    output = natsorted(os.listdir())
    
    for idx,v1 in enumerate(output):
        if(v==v1):
            print(v, v1)
            img_out = cv2.imread(v1, cv2.IMREAD_UNCHANGED)
            subtracted = cv2.subtract(img_out, img_erode)
        else:
            continue
    
    plt.imshow(cv2.cvtColor(subtracted, cv2.COLOR_BGR2RGB))
    plt.show()

运行报错信息:

---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
/tmp/ipykernel_33/3647166721.py in <module>
     43             print(v, v1)
     44             img_out = cv2.imread(v1, cv2.IMREAD_UNCHANGED)
---> 45             subtracted = cv2.subtract(img_out, img_erode)
     46 #             if img_out.shape[2] == 4:
     47 #                   a1 = ~img_out[:,:,3]

error: OpenCV(4.5.4) /tmp/pip-req-build-jpmv6t9_/opencv/modules/core/src/arithm.cpp:647: error: (-209:Sizes of input arguments do not match) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function 'arithm_op'

报错核心原因:参与cv2.subtract运算的两个矩阵尺寸或通道数不匹配,要么两张图分辨率不一致,要么一张为3通道RGB格式、另一张为带Alpha通道的4通道格式,OpenCV算术运算要求两个输入矩阵shape完全一致。
该方案其他逻辑问题:两层遍历像素的循环仅反复给同一个变量赋值,未实现任何像素提取、匹配的有效逻辑;反复切换工作目录的写法极易引发文件读取、路径匹配异常;图像减法的思路本身不适配当前场景——参考图是带实色色块的图、目标图是轮廓线稿,二者像素值差异极大,减法无法得到预期的彩色轮廓结果。

方案2:直接提取像素做颜色迁移

实现逻辑:直接从第一幅图像中提取颜色像素,迁移到第二幅图像,但由于图像包含3个不同颜色的分区,无法实现区域对应匹配,达不到预期效果。
对应实现代码:

import os
import cv2
from natsort import natsorted
import matplotlib.pyplot as plt
os.chdir('/kaggle/input/maskedoutput')
stroke_list = natsorted(os.listdir())

for i,v in enumerate(stroke_list):
    image = cv2.imread(v, cv2.IMREAD_UNCHANGED)
    
    if image.shape[2] == 4:    
          a1 = ~image[:,:,3]  
          image = cv2.add(cv2.merge([a1,a1,a1,a1]), image)   
          image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
    else:
        image = cv2.cvtColor(image, cv2.COLOR_RGBA2RGB)
    plt.imshow((image))
    plt.show()
    copy = image.copy()

    kernel = np.ones((15,15), np.uint8)
    closing = cv2.morphologyEx(copy, cv2.MORPH_CLOSE, kernel)
    img_erode = cv2.erode(closing, kernel, iterations=1)# 消除黑色轮廓
    height, width, channel = img_erode.shape
    
    for x1 in range(0,width):
        for y1 in range(0,height):
            channels_x1y1 = img_erode[y1,x1]
            
    os.chdir('/kaggle/input/maskstrokes')
    output = natsorted(os.listdir())
    
    for idx,v1 in enumerate(output):
        if(v==v1):
            print(v, v1)
            img_out = cv2.imread(v1, cv2.IMREAD_UNCHANGED)
            height2, width2, channel2 = img_out.shape
    
    for x1 in range(0,width2):
        for y1 in range(0,height2):
            channels_x1y1 = img_out[y1,x1]
         
        else:
            continue
    
    plt.imshow(cv2.cvtColor(img_out, cv2.COLOR_BGR2RGB))
    plt.show()

该方案核心问题:没有做分区识别和匹配逻辑,逐像素直接迁移无法对应多色块分区的映射关系,自然无法得到正确结果。

可行实现步骤

  • 第一步:统一输入格式
    读取两张图像后,统一转为3通道BGR格式,将两张图resize到完全相同的分辨率,从根源上避免矩阵尺寸不匹配的报错;放弃反复切换工作目录的写法,直接拼接完整文件路径完成文件读写,减少路径异常。
  • 第二步:提取参考图分区基准色
    对第一幅带色块的参考图做闭运算、腐蚀操作去除黑色轮廓后,用连通域分析拆分出不同颜色的独立封闭分区,计算每个分区的平均RGB值作为该区域的基准填充色,替换无意义的逐像素空循环。
  • 第三步:提取目标图待填充区域
    对第二幅轮廓线稿图做二值化处理,拆分出黑色轮廓线、待填充的封闭区域掩码,由于两张图结构完全一致,待填充区域和参考图的色块分区坐标是一一对应的,直接按位置做匹配即可。
  • 第四步:按区域填充颜色
    将参考图对应分区的基准色填充到目标图的对应待填充区域,完成颜色迁移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 01:15:39