-1

I have a categorical image with the size of 14400 * 7200. I am trying the following code to colorize the values ​​in this image. It works but takes a long time. How can I do this in a shorter time?

        color_map = {}
        for category in np.unique(np.arange(201, dtype=np.uint8)):
            color_map[category] = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))   
            
        color_map["0"]=(128, 64,128) 
        color_map["1"]=(232, 35,244)
        color_map["2"]=( 70, 70, 70)
        color_map["3"]=(156,102,102)
        color_map["4"]=(255,255,204)
        color_map["5"]=(153,153,153)
        color_map["6"]=(30,170, 250)
        color_map["7"]=(30,170, 250)
        color_map["8"]=(52,219, 163)
        color_map["9"]=(0,102, 102)
        color_map["10"]=( 180,130,70)
        color_map["11"]=(60, 20, 220)
        color_map["12"]=(60, 20, 220)
        color_map["13"]=(255, 0, 0)
        color_map["14"]=(255, 0, 0)
        color_map["15"]=(255, 0, 0)
        color_map["16"]=(255, 0, 0)
        color_map["17"]=(255, 0, 0)
        color_map["18"]=(255, 0, 0)
        color_map["40"]=(0, 0, 0)
        color_map["41"]=(0, 1, 0)
        color_map["42"]=(0, 2, 0)
        color_map["43"]=(0, 3, 0)
        color_map["44"]=(0, 4, 0)
        color_map["45"]=(0, 5, 0)
        color_map["46"]=(0, 6, 0)
        color_map["47"]=(0, 7, 0)
        color_map["48"]=(0, 8, 0)
        color_map["49"]=(0, 9, 0)
        color_map["50"]=(0, 10, 0)
        color_map["51"]=(0, 11, 0)
        
        a_array = np.array(a)

        
        category_image = a_array
        colored_image = np.zeros((category_image.shape[0], category_image.shape[1], 3), dtype=np.uint8)
        for h in range(category_image.shape[0]):
            for g in range(category_image.shape[1]):
                category = category_image[h, g]
                colored_image[h, g] = color_map[str(category)]#normalde str yok
        cv2.imwrite(j, colored_image)

thanks for your solutions

  • 2
    Does your *"binary"* image currently have 52 colours? – Mark Setchell Aug 21 '23 at 11:08
  • 1
    It would be best if you show which part takes a lot of time and then also, what is a lot of time. Now you have 2 for loops that can take up a lot of time, but we're unsure of which. – moojen Aug 21 '23 at 11:18
  • @MarkSetchell I color my categorical image, yes there are 52 categories – geomaticpoly Aug 21 '23 at 11:31
  • @moojen hi, the last for loop is taking a very long time. – geomaticpoly Aug 21 '23 at 11:32
  • 1
    Instead of looping over every pixel, use numpy masking to choose indices in `colored_image` and assign to them? – AKX Aug 21 '23 at 12:02
  • 1
    You want to apply a colormap, and tagged it with OpenCV... so, use [`applyColorMap`](https://docs.opencv.org/4.x/d3/d50/group__imgproc__colormap.html#gacb22288ddccc55f9bd9e6d492b409cae)? – Dan Mašek Aug 21 '23 at 13:22
  • 1
    have a look at opencv's lookup-table function: `cv2.LUT`, see https://learnopencv.com/applycolormap-for-pseudocoloring-in-opencv-c-python/ – Micka Aug 21 '23 at 13:37
  • 2
    @Micka `LUT` needs input and output to have same channel count, not a good choice. Also that article is rather old and pre-dates addition of an overload to `applyColorMap` supporting user defined colormaps (and that function actually can map grayscale to colour). – Dan Mašek Aug 21 '23 at 14:30
  • 1
    @DanMašek according to some older benchmarking, LUT is veeeery fast. Depending on the specific problem it might even be faster to use a 3 channel input (converted or directly created as 3 channel with only gray pixels) and use LUT to map it the 3 channel output. But yes, applyColorMap is probably faster for 1-to-3 channel mapping. – Micka Aug 22 '23 at 07:18

1 Answers1

2

Instead of looping over every pixel, use numpy masking to choose indices in colored_image and assign to them:

for category in np.unique(category_image):
    colored_image[category_image == category] = color_map[category]

On my machine, this runs through a random 1024x1024 image in 0.16 seconds.

Note you'll need to change color_map's keys to be ints, not strings:

color_map[0] = (128, 64, 128)
color_map[1] = (232, 35, 244)
# etc ...
AKX
  • 152,115
  • 15
  • 115
  • 172