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

peony: <p>I am having this error:</p>
<p><code>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 ()'</code></p>
<p>that traces back to this code:</p>
<p><code>heatmap=cv2.applyColorMap(np.uint8(cam),cv2.COLORMAP_JET)</code></p>
<p>Here is my full code ( I am trying grad-cam in my subset):</p>
<pre><code class="lang-auto">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 -&gt; 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&gt;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)
</code></pre>
<p>I have tried</p>
<p><code>cam = np.uint8(224 * cam)</code> and <code>cam = (cam/256).astype(np.uint8)</code> but nothing seems to solve this problem.</p>
<p>Any suggestions for me? Thank you in advance</p>

ptrblck: <p>Check the shape and <code>dtype</code> of the input you are passing to the OpenCV method and make sure it’s using a single or 3 channels in <code>uint8</code>.</p>

peony: <p>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.</p>
<p>Here is my full code:</p>
<pre><code class="lang-auto">    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&gt;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
</code></pre>

ptrblck: <p>Could you print all output shapes or directly post a minimal and executable code snippet to reproduce the issue?</p>

peony: <p>Hello <a class="mention" href="/u/ptrblck">@ptrblck</a></p>
<p>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)</p>
<blockquote>
<p>cam = np.mean(cam, axis=1).squeeze()</p>
</blockquote>
<p>thank you for guidance</p>