How to solve error: cv::ColorMap only supports source images of type CV_8UC1 or CV_8UC3 in function 'cv::colormap::ColorMap::operator ()'

I am having this error:

error: OpenCV(4.7.0) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\colormap.cpp:736: error: (-5:Bad argument) cv::ColorMap only supports source images of type CV_8UC1 or CV_8UC3 in function 'cv::colormap::ColorMap::operator ()'

that traces back to this code:

heatmap=cv2.applyColorMap(np.uint8(cam),cv2.COLORMAP_JET)

Here is my full code ( I am trying grad-cam in my subset):

for i_batch, (data, target, meta) in enumerate(tqdm(dataloader_test)):
  
        data, target = map(lambda x: x.to(device), (data, target))
        
        for imname,  metaitemm in  metadata_test.items():

            output = model(data)
           
            output.argmax(dim=1) 
            output[:, 5].sum().backward()
            metaitem = metadata_test[imname]
            impath = metaitem['impath']
    
            impath = cv2.imread(impath)
            

            imgdata = torch.Tensor(impath)
            imgdata = torch.unsqueeze(imgdata, 0)

    
            imgdata = torch.einsum('n h w c -> n c h w', imgdata)
            
            
           
            

            model.layer4[-1].register_forward_hook(forward_hook)
            model.layer4[-1].register_backward_hook(backward_hook)
           
            
            grads=grad[0].cpu().data.numpy().squeeze()
            

            
            fmap=activation[0].cpu().data.numpy().squeeze()
            
            tmp=grads.reshape([grads.shape[0],-1])
          
            weights=np.mean(tmp,axis=1)
            
            
            cam = np.zeros(grads.shape[1:])
            for i,w in enumerate(weights):
                cam += w*fmap[i,:]
            #relu
            #cam=(cam>0)*cam
            cam = np.maximum(cam, 0)
            #print("cam.shape",cam.shape)
            #normalize heatmap
            #cam=cam/cam.max()*224
            cam /= np.max(cam)
            # make the heatmap to be a numpy array
            
            npic = np.array(torchvision.transforms.ToPILImage()(impath).convert('RGB'))
            cam = cv2.resize(cam,(npic.shape[1], npic.shape[0]))
            #cam = np.uint8(224 * cam)
            #cam = (cam/256).astype(np.uint8)
            heatmap=cv2.applyColorMap(np.uint8(cam),cv2.COLORMAP_JET)

I have tried

cam = np.uint8(224 * cam) and cam = (cam/256).astype(np.uint8) but nothing seems to solve this problem.

Any suggestions for me? Thank you in advance

Check the shape and dtype of the input you are passing to the OpenCV method and make sure it’s using a single or 3 channels in uint8.

turns out I have 7 channels. How do we change it to 3? My images are normal images so I don’t understand why it can have 7 channels.

Here is my full code:

    for idx, (data, target, meta) in list(enumerate(tqdm(dataloader_test)))[:500]:
        
        data, target = map(lambda x: x.to(device), (data, target))

        output = model(data)
        model.zero_grad()
        output[:,5].sum().backward()
        grads=grad[0].cpu().data.numpy().squeeze()
        fmap=activation[0].cpu().data.numpy().squeeze()
        tmp=grads.reshape([grads.shape[0],-1])
        print(fmap.shape)
        print(grads.shape)
        # mean value of the gradients of  featuremap
        weights=np.mean(tmp,axis=1)
        cam = np.zeros(grads.shape[1:])
        for i,w in enumerate(weights):
            cam += w*fmap[i,:]
        #relu
        cam=(cam>0)*cam

        cam=cam/cam.max()*255
        

        for d, t, m in zip(data, target, meta):
            print('m', m['impath'])
   
            img = cv2.imread(m['impath'])
            
           # img_plot = plt.imshow(img)
            print('cam before resize', cam.shape)
            #plt.show()
            img = np.array(torchvision.transforms.ToPILImage()(img).convert('RGB'))
            print('image shape', img.shape)
            cam = cv2.resize(cam,(img.shape[1], img.shape[0]))
            cam = np.uint8(255 * cam)
            #print(np.max(cam), np.min(cam), cam.dtype)
            print('cam shape', cam.shape)
            #cam = cam.numpy()
            print(np.max(cam), np.min(cam), cam.dtype)



            #cam = data.astype(np.uint8)
            heatmap=cv2.applyColorMap(np.uint8(cam),cv2.COLORMAP_JET)
            cam_img=img*0.7+heatmap*0.3
            print(cam_img.shape)
            cv2.imwrite('./visualize/map'+str(count)+'.jpg', cam_img)
            count = count + 1

Could you print all output shapes or directly post a minimal and executable code snippet to reproduce the issue?

1 Like

Hello @ptrblck

I printed all the output shapes and learned that averaging the channels of the activations solved the problem (I got confused because I was following two tutorials, the other one doesn’t do the averaging apparently)

cam = np.mean(cam, axis=1).squeeze()

thank you for guidance