arizona_3
arizona_3

Reputation: 51

how to extract individual pixel(color/rgb) value from one image and transfer to the second image

I'm trying to transfer pixel value from one image and transferring it to other image. so, basically I have 2 images and my goal is to transfer colors of img1 to 2 according to the regions.

link to img1 img2 and expected image

here I am aware to extract color channel out of an image , but I am not able to achieve the required result. I'll highly appreciate any help. my approach:

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()

here i'm meaning to first erode the original coloured image in order to supress the black outline. Then next extracting color pixels and in the image2 after reading it i'm trying to subtract it with img1 the residual would be the colored outline, but this code is not working gives mte this error:

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

another approach was to directly pick color pixels from image1 and directly transfer it to second image but as you can see the image has 3 parts with different colors and so its not happening code:

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()

Blocker image blocker image

Upvotes: 1

Views: 2284

Answers (1)

Jeru Luke
Jeru Luke

Reputation: 21203

I prepared a quick fix solution based on the expected output.

I used the following image as input:

enter image description here

Code:

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]

enter image description here

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

enter image description here

# 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()

In the following, we iterate through each contour. For each contour:

  • get the centroid of the contour (centroid)
  • get the color at the centroid from original image (color)
  • draw the contour with that color on the copy of original image (img2)

code:

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)

Now we subtract the original from the newly drawn image r. Based on mask, wherever pixels are white we assign white in r

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

enter image description here

Update:

Expected result for the latest image. The green shade is present on the border as expected. This was obtained using the same code without any changes:

enter image description here

Upvotes: 2

Related Questions