Pyqtgraph 将选定的感兴趣区域放在不同颜色的地图中

Pyqtgraph Put the Selected Region of Interest in a Different Color Map

这是从一个 pyqtgraph 示例稍作修改的代码片段:

import numpy as np
import cv2
import pyqtgraph as pg

pg.setConfigOptions(imageAxisOrder='row-major')

## Create image to display
image = cv2.imread('panda.jpg')

#Transpose the image
def picturetranspose(picture):
    shape = picture.shape
    result = np.empty((shape[1],shape[0],shape[2]),dtype= np.uint8)
    for i in range(0,3):
        result[:,:,i] = np.transpose(picture[:,:,i])
    return result
    
arr = np.rot90(picturetranspose(image))
#arr = cv2.applyColorMap(arr, cv2.COLORMAP_JET)

app = pg.mkQApp("ROI Examples")
w = pg.GraphicsLayoutWidget(show=True, size=(1000,800), border=True)
w.setWindowTitle('pyqtgraph example: ROI Examples')

w1 = w.addLayout(row=0, col=0)
v1a = w1.addViewBox(row=1, col=0, lockAspect=True)
v1b = w1.addViewBox(row=2, col=0, lockAspect=True)
img1a = pg.ImageItem(arr)
v1a.addItem(img1a)
img1b = pg.ImageItem()
v1b.addItem(img1b)

rois = []
rois.append(pg.PolyLineROI([[80, 60], [90, 30], [60, 40]], pen=(6,9), closed=True))

def update(roi):
    img1b.setImage(roi.getArrayRegion(arr, img1a), levels=(0, arr.max()))
    
for roi in rois:
    roi.sigRegionChanged.connect(update)
    v1a.addItem(roi)

update(rois[-1])
if __name__ == '__main__':
    pg.exec()

此处图像“panda.jpg”由以下人员提供: https://drive.google.com/drive/folders/1ejY0CjfEwS6SGS2qe_uRX2JvlruMKvPX?usp=sharing.

运行 上面的代码并稍微移动 ROI(感兴趣区域)将得到:

一切正常。我现在要做的是把选中的ROI做成不同的colormap。我的尝试如下:如果我在 arr 的定义之后添加 arr = cv2.applyColorMap(arr, cv2.COLORMAP_JET) 行,那么我将得到的是:

这成功地转换了色彩空间,但不是我想要的方式,因为我只需要将所选区域放在新的色彩图中。我的下一次尝试是用 img1b.setImage(cv2.applyColorMap(roi.getArrayRegion(arr, img1a), cv2.COLORMAP_JET), levels=(0, arr.max())) 代替 img1b.setImage(roi.getArrayRegion(arr, img1a), levels=(0, arr.max()))。但这会导致错误消息:

我应该如何进行?

编辑: 通过写 arr2 = cv2.applyColorMap(arr, cv2.COLORMAP_JET) 并写 img1b.setImage(roi.getArrayRegion(arr2, img1a), levels=(0, arr.max())) 代替 img1b.setImage(roi.getArrayRegion(arr, img1a), levels=(0, arr.max())),我可以得到以下内容:

我现在还需要做的就是在不同颜色的地图中制作所选区域(我用红色标记)。最好是选择的区域在不同的颜色图中而不是边界矩形中。

编辑: 最后,我通过将 update 方法替换为以下方法解决了我的问题:

def update(roi):
    arr_copy = arr.copy()
    
    slices, tr = roi.getArraySlice(arr, img1a, returnSlice=True)
    
    colormapped = roi.getArrayRegion(arr2, img1a)
    
    newslices = (slice(slices[0].start, slices[0].start + colormapped.shape[0], None),
                 slice(slices[1].start, slices[1].start + colormapped.shape[1], None),
                 slice(None,None,None))
    
    gray_original = np.dot(arr_copy[newslices][...,:3], [0.299, 0.587, 0.114])
    gray_colormapped = np.dot(colormapped[...,:3], [0.299, 0.587, 0.114])
    gray_original_masked = ma.array(gray_original,mask = gray_colormapped).filled(fill_value = 0)
    
    complement = np.empty(gray_original_masked.shape)
    complement[gray_original_masked == 0] = 1
    complement[gray_original_masked != 0] = 0
    
    interior_croped_0 = ma.array(arr_copy[newslices][:,:,0],mask = complement).filled(fill_value = 0)
    interior_croped_1 = ma.array(arr_copy[newslices][:,:,1],mask = complement).filled(fill_value = 0)
    interior_croped_2 = ma.array(arr_copy[newslices][:,:,2],mask = complement).filled(fill_value = 0)
    
    original_color_masked = np.empty(arr_copy[newslices].shape)
    original_color_masked[:,:,0] = interior_croped_0
    original_color_masked[:,:,1] = interior_croped_1
    original_color_masked[:,:,2] = interior_croped_2
    
    final = original_color_masked + colormapped 
    arr_copy[newslices] = final
    
    img1a.setImage(arr_copy, levels=(0, arr.max()))

感谢 D Malan 给了我使用切片的提示。

您可以使用 getArraySlice.

获取需要更新的原始数组中的切片

将您的 update 方法更改为:

arr2 = cv2.applyColorMap(arr, cv2.COLORMAP_JET)

def update(roi):
    img1b.setImage(roi.getArrayRegion(arr, img1a), levels=(0, arr.max()))

    # Get a copy of the original array that can be modified
    arr_copy = arr.copy()
    # Get the slices of the ROI
    slices, tr = roi.getArraySlice(arr, img1a, returnSlice=True)
    # Update the slices to have the values of the colourmap
    arr_copy[slices] = arr2[slices]
    # Update the image with the new values
    img1a.setImage(arr_copy, levels=(0, arr.max()))