【问题标题】:how to extract individual pixel(color/rgb) value from one image and transfer to the second image如何从一张图像中提取单个像素(颜色/RGB)值并转移到第二张图像
【发布时间】:2022-06-14 19:29:12
【问题描述】:

我正在尝试将像素值从一张图像传输到另一张图像。 所以,基本上我有 2 张图像,我的目标是根据区域将 img1 的颜色转换为 2。

link to img1 img2 and expected image

在这里我知道要从图像中提取颜色通道,但我无法达到所需的结果。我将非常感谢任何帮助。 我的方法:

import cv2
import numpy as np 
import os
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)# to supress black outline
    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()

这里我的意思是首先侵蚀原始彩色图像以抑制黑色轮廓。然后接下来提取颜色像素,在读取它之后在 image2 中我试图用 img1 减去它,残差将是彩色轮廓,但是这段代码不起作用给 mte 这个错误:

    ---------------------------------------------------------------------------
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'

另一种方法是直接从 image1 中选取颜色像素并将其直接传输到第二张图像,但正如您所见,图像有 3 个不同颜色的部分,因此不会发生 代码:

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)# to supress black outline
    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()

拦截器图片

【问题讨论】:

  • 查找轮廓 -> 找到每个轮廓的质心 -> 在质心处获取颜色 -> 将该颜色应用于轮廓
  • 欢迎来到 Stackoverflow!您是否只想将图像 1 中的彩色补丁粘贴到图像 2 上,或者您真的想在这些区域周围绘制彩色线条,如示例输出所示?请准确说出您的需求!
  • @Markus 嗨!,我明确地寻找一种解决方案,将 (img1->img2) 对应的 blob 的颜色像素转移到另一个
  • @arizona_3 是的,您必须对图像进行二值化以获得轮廓。
  • @JeruLuke 绝对!!现在尝试在具有更少或更多彩色斑点/元素的不同图像上进行此操作

标签: opencv image-processing rgb pixel opencv3.0


【解决方案1】:

我根据预期输出准备了一个快速修复解决方案。

我使用以下图片作为输入:

代码:

img = cv2.imread('colored_objects.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# binary mask
mask = cv2.threshold(gray,10,255,cv2.THRESH_BINARY)[1]

# inverted binary mask
th = cv2.threshold(gray,10,255,cv2.THRESH_BINARY_INV)[1]

# finding external contours based on inverted binary mask
contours, hierarchy = cv2.findContours(th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# create copy of original image to draw contours 
img2 = img.copy()

在下面,我们遍历每个轮廓。 对于每个轮廓:

  • 获取轮廓的质心 (centroid)
  • 从原始图像中获取质心的颜色 (color)
  • 在原图副本上用该颜色绘制轮廓 (img2)

代码:

for c in contours:
    M = cv2.moments(c)
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])
    centroid = (cx, cy)
    color = tuple(img[cy, cx])
    color = ( int (color [ 0 ]), int (color [ 1 ]), int (color [ 2 ])) 
    print(color)
    img2 = cv2.drawContours(img2, [c], 0, tuple(color), -1)

现在我们从新绘制的图像r 中减去原始图像。基于mask,只要像素是白色,我们就会在r中指定白色

r = img2 - img
r[mask == 255] = (255, 255, 255)

【讨论】:

  • 谢谢!我现在在不同的图像上尝试相同的方法,其中没有更多元素。
  • @arizona_3 希望它适用于其他图像
  • 嘿耶鲁卢克!它适用于大多数情况:))),但是我遇到了一个创建阻止程序的图像...T_T ive 更新了问题本身中的图像...
猜你喜欢
  • 1970-01-01
  • 2014-04-22
  • 2012-05-27
  • 1970-01-01
  • 2013-05-20
  • 2019-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多