1

I'm having some problems with dumping a dictionary to a json file. The dictionary is made up of color tuples/values from an image, and is generated like so:

import cv2, json

img = cv2.imread("bg.png")
HEIGHT, WIDTH = img.shape[:2]

colors = set({})
col_dict = {}
index = 0

for h in range(HEIGHT):
    for w in range(WIDTH):
        if tuple(img[h, w]) in colors:
            continue
        else:
            colors.add(tuple(img[h, w]))
            col_dict[str(index)] = list(img[h, w])
            index += 1

The following loop will extract all the different types of color values in an image and stores them in the dictionary, using the index variable as the key. The colors set variable is used in another part of my program, so it can be ignored.

The loop successfully creates a dictionary, but when executing the following code:

with open("file.json", "w") as infile:
    json.dump(col_dict, infile, indent=2)

The following error is produced:

TypeError: Object of type uint8 is not JSON serializable

The code works when I define a dictionary and it's values manually, like so:

colors = {
    "0" : (109, 87, 34),
    "1" : (209, 87, 34),
    "2" : (85, 98, 34), ...}

with open("file.json", "w") as infile:
    json.dump(colors, infile)

I have no idea why it isn't working now, it still works for other programs that do the same thing. Thanks in advance.

2
  • Check/print the type of img[h, w] where you do col_dict[str(index)] = list(img[h, w]). Commented Nov 18, 2021 at 11:18
  • @Matthias I've tested it and it returns a <class 'numpy.ndarray'> Commented Nov 18, 2021 at 11:33

1 Answer 1

1

I've found the problem with the code. CV2 image objects are numpy.ndarrays, and each pixel color value is a numpy.uint8 data type. Since json files do not understand numpy uint8 integers, it produced the error TypeError: Object of type uint8 is not JSON serializable.

Here is the solution to my code:

import cv2, json

img = cv2.imread("bg.png")
HEIGHT, WIDTH = img.shape[:2]

colors = set({})
col_dict = {}
index = 0

for h in range(HEIGHT):
    for w in range(WIDTH):
        if tuple(img[h, w]) in colors:
            continue
        else:
            value = (int(img[h, w][0]), int(img[h, w][1]), int(img[h, w][2]))  # This converts each BGR value from uint8 to int.
            colors.add(tuple(img[h, w]))
            col_dict[str(index)] = value
            index += 1

with open("file.json", "w") as infile:
    json.dump(col_dict, infile, indent=2)

All I needed to do was convert the numpy uint8 object to a python integer.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.