'Labeling images using Python
I recently stumbled upon this question: Interactive labeling of images in jupyter notebook which I found quite interesting.
Having little experience in Python coding, I tried to run the provided code from the answer using a Jupyter Notebook, but I somehow cannot get it to work. I believe that I am doing something wrong when importing the images. I am trying to import all images from a folder called "images" which is located in "PATH".
Here is the complete code:
import cv2
import os
import ipywidgets as widgets
import functools
images_list = []
os.chdir(PATH)
# Load in the images
for filepath in os.listdir('images/'):
images_list.append(cv2.imread('images/{0}'.format(filepath),0))
COLS = 4
ROWS = 2
IMAGES = images_list
IMG_WIDTH = 200
IMG_HEIGHT = 200
def on_click(index):
print('Image %d clicked' % index)
rows = []
for row in range(ROWS):
cols = []
for col in range(COLS):
index = row * COLS + col
image = widgets.Image(
value=IMAGES[index], width=IMG_WIDTH, height=IMG_HEIGHT
)
button = widgets.Button(description='Image %d' % index)
# Bind the click event to the on_click function, with our index as argument
button.on_click(functools.partial(on_click, index))
# Create a vertical layout box, image above the button
box = widgets.VBox([image, button])
cols.append(box)
# Create a horizontal layout box, grouping all the columns together
rows.append(widgets.HBox(cols))
# Create a vertical layout box, grouping all the rows together
result = widgets.VBox(rows)
Edit
After fixing the syntax error, I get the following error:
---------------------------------------------------------------------------
TraitError
Traceback (most recent call last) <ipython-input-87-2ca2a1eb59b4> in <module>()
36 index = row * COLS + col
37 image = widgets.Image(
---> 38 value=IMAGES[index], width=IMG_WIDTH, height=IMG_HEIGHT
39 )
40 button = widgets.Button(description='Image %d' % index)
~\Anaconda3\lib\site-packages\ipywidgets\widgets\widget.py in __init__(self, **kwargs)
409 """Public constructor"""
410 self._model_id = kwargs.pop('model_id', None)
--> 411 super(Widget, self).__init__(**kwargs)
412
413 Widget._call_widget_constructed(self)
~\Anaconda3\lib\site-packages\traitlets\traitlets.py in __init__(self, *args, **kwargs)
995 for key, value in kwargs.items():
996 if self.has_trait(key):
--> 997 setattr(self, key, value)
998 else:
999 # passthrough args that don't set traits to super
~\Anaconda3\lib\site-packages\traitlets\traitlets.py in __set__(self, obj, value)
583 raise TraitError('The "%s" trait is read-only.' % self.name)
584 else:
--> 585 self.set(obj, value)
586
587 def _validate(self, obj, value):
~\Anaconda3\lib\site-packages\traitlets\traitlets.py in set(self, obj, value)
557
558 def set(self, obj, value):
--> 559 new_value = self._validate(obj, value)
560 try:
561 old_value = obj._trait_values[self.name]
~\Anaconda3\lib\site-packages\traitlets\traitlets.py in _validate(self, obj, value)
589 return value
590 if hasattr(self, 'validate'):
--> 591 value = self.validate(obj, value)
592 if obj._cross_validation_lock is False:
593 value = self._cross_validate(obj, value)
~\Anaconda3\lib\site-packages\traitlets\traitlets.py in validate(self, obj, value)
2024 if isinstance(value, bytes):
2025 return value
-> 2026 self.error(obj, value)
2027
2028
~\Anaconda3\lib\site-packages\traitlets\traitlets.py in error(self, obj, value)
623 e = "The '%s' trait must be %s, but a value of %r was specified." \
624 % (self.name, self.info(), repr_type(value))
--> 625 raise TraitError(e)
626
627 def get_metadata(self, key, default=None):
TraitError: The 'value' trait of an Image instance must be a bytes object, but a value of
array([[232, 242, 243, ..., 243, 246, 232],
[244, 254, 255, ..., 254, 255, 243],
[244, 254, 255, ..., 254, 255, 242],
...,
[242, 253, 253, ..., 254, 254, 243],
[245, 255, 255, ..., 255, 255, 244],
[238, 249, 248, ..., 245, 245, 234]], dtype=uint8)
<class 'numpy.ndarray'>
was specified.
Edit
Here is my Jupyter Notebook version:
Solution 1:[1]
The code you copied has a missing colon at the end of the second for line, which should look like this:
for col in range(COLS):
(I would recommend a good IDE, or, at the very least, a syntax checker, to catch these sorts of errors, though!)
Once you've fixed any syntax issues, you can verify if you really have any actual problems with the way you're importing the images. But from what I can see, your code is fine - you're opening a bunch of files as greyscale images and passing them to the code from the linked question. (If you still have issues after the syntax errors are gone, though, you can edit this question or post another.)
Solution 2:[2]
For what it's worth, you can also use QSL for this task. I added an example to the original question but, in your case, it could be as simple as the following. You can add inputs from within the widget itself (using the "Add New Label Type" button). More information about qsl here. Full disclosure, QSL is one of my projects.
import glob
from IPython.display import display
import qsl
widget = qsl.MediaLabeler(
items=[{"target": f} for f in glob.glob("images/*")],
jsonpath="labels.json"
)
display(widget)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Niayesh Isky |
| Solution 2 | Fausto Morales |

