1

iam trying to apply a heat map on a selected portion[people's face] of my picture. Here is what i had done so far... the rectangle will be applied to the face . the face will be cropped heat map will be applied to the cropped image.

 # Draw a rectangle around the faces
    for (x, y, w, h) in faces:
        cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
        crop_img = image[y:y+h, x:x+w]

 # Cropping Area
            # Color Mapping Area
            images = cv2.imread(crop_img, 0)
            colormap = plt.get_cmap('inferno')
            heatmap = (colormap(images) * 2**16).astype(np.uint16)[:,:,:3]
            heatmap = cv2.cvtColor(heatmap, cv2.COLOR_RGB2BGR)

# Saving Color Map   
            img_names = "heatimage{}.png".format(i)
            cv2.imwrite(img_names, heatmap)
            print("{} written!".format(img_names))
            img = cv2.imread(img_names,0)
            cv2.imshow('heatmap{}'.format(i),heatmap)

i was able to save the cropped image and rectangle pointing faces separately but i need 1. to make the rectangle to be a heat map ,without cropping separately,in my original image. 2. other part of the image has to be normal

EDITED

Draw a rectangle around the faces

for (x, y, w, h) in faces:
    cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
    crop_img = image[y:y+h, x:x+w]
    sample = cv2.imread("sample.jpg",cv2.COLOR_BGR2GRAY)
    colormap = cm.get_cmap('inferno', 256)
    cmp = cm.ScalarMappable(cmap='inferno')
    # create 1D float gradient from 0 to 1 with 256 increments 
    # convert to rgba in range 0 to 255 (via bytes=True)
    # remove alpha channel and reshape to 256x1 3 channel from (256, 4)
    # convert rgb to bgr
    cmap = np.linspace(0, 1, 256, endpoint=True)
    cmap = cmp.to_rgba(cmap, bytes=True)
    cmap = cmap[:, 0:-1].reshape((256, 1, 3))
    cmap = cv2.cvtColor(cmap, cv2.COLOR_RGB2BGR)
    # apply color map to crop
    crop_mapped = cv2.applyColorMap(crop_img, cmap)
    # put color mapped crop back into input
    result = sample.copy()
    result = cv2.cvtColor(result, cv2.COLOR_GRAY2BGR)
    result[y:y+h, x:x+w] = crop_mapped
    # save result
    cv2.imwrite('IRimage.jpg', result)
    # show result
    cv2.imshow("result", result)
    i+=1
    cv2.imshow("Faces found", image)

If i have more than one face , how can i apply color filter to both the faces?

natasha
  • 41
  • 2
  • It would be helpful if you posted the heatmap and the image you want to apply it to – Warpstar22 May 26 '20 at 21:06
  • I believe that you will have to crop the image, apply the colormap to the cropped image, then put the color mapped crop image back into your original. I do not think there is a way to apply a colormap to a portion of an image without either cropping or color mapping the whole image and then combining it with the original. – fmw42 May 26 '20 at 21:17

2 Answers2

0

If I understand correctly, you're trying to display the portion of a heatmap that's on the face of a person.Try this

alpha = 0.5
image[y:y+h, x:x+w] = alpha * image[y:y+h, x:x+w] + (1 - alpha) * heatmap[y:y+h, x:x+w]
cv2.imshow("preview", image)
soumith
  • 536
  • 1
  • 3
  • 12
0

I believe that you will have to crop the image, apply the colormap to the cropped image, then put the color mapped crop image back into your original. I do not think there is a way to apply a colormap directly to a portion of an image.

Here is how I do the above in Python/OpenCV.

  • Read the input as grayscale
  • Crop the image where you want it to be color mapped
  • Load the colormap from Matplotlib and convert it to a BGR image
  • Apply the colormap to the cropped image
  • Convert the input to 3 channel gray and insert the color mapped cropped image back in the correct location.
  • Save the results


Input:

enter image description here

import cv2
import numpy as np
import matplotlib.cm as cm

# read image and convert to gray
img = cv2.imread('redhat_gray.jpg', cv2.COLOR_BGR2GRAY)

# crop image
crop = img[140:240, 70:170]

# get colormap from matplotlib and normalize
colormap = cm.get_cmap('inferno', 256)
cmp = cm.ScalarMappable(cmap='inferno')

# create 1D float gradient from 0 to 1 with 256 increments 
# convert to rgba in range 0 to 255 (via bytes=True)
# remove alpha channel and reshape to 256x1 3 channel from (256, 4)
# convert rgb to bgr
cmap = np.linspace(0, 1, 256, endpoint=True)
cmap = cmp.to_rgba(cmap, bytes=True)
cmap = cmap[:, 0:-1].reshape((256, 1, 3))
cmap = cv2.cvtColor(cmap, cv2.COLOR_RGB2BGR)
#print(cmap)

# apply color map to crop
crop_mapped = cv2.applyColorMap(crop, cmap)

# put color mapped crop back into input
result = img.copy()
result = cv2.cvtColor(result, cv2.COLOR_GRAY2BGR)
result[140:240, 70:170] = crop_mapped

# save result
cv2.imwrite('redhat_gray_rectangle_inferno.jpg', result)

# show result
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()


Result:

enter image description here

fmw42
  • 46,825
  • 10
  • 62
  • 80
  • If i have more than one face , how can i apply color filter to both the faces? – natasha May 27 '20 at 07:15
  • Make multiple crops and then reinsert them back after applying the heat map to them. Or apply the heat map to the full image, then make a mask from all the areas you want the heat map applied. Then use the mask to combine the original and the colorized images so that the heat map shows where the mask is white and the original shows where the mask is black. – fmw42 May 27 '20 at 16:36
  • result[y:y+h, x:x+w] = crop_mapped # will this works for multiple crop and paste ? – natasha May 30 '20 at 04:23
  • Yes, you just have to repeat it for each section you want – fmw42 May 30 '20 at 04:25