KeyError: class 'numpy.object_' while downloading image dataset using imread - python

I am trying to download images from URLs using imread. After downloading about 700 images, I see KeyError: class 'numpy.object_' . I am really not familiar with numpy and Conda libraries. Any help would be appreciated
for i in range(len(classes)):
if not os.path.exists(saved_dirs[i]):
os.mkdir()
saved_dir = saved_dirs[i]
for url in urls[i]:
# print(url)
img = io.imread(url)
saved_path = os.path.join(saved_dir, url[-20:])
io.imsave(saved_path, img)
Trigger URL: https://requestor-proxy.figure-eight.com/figure_eight_datasets/open-images/test/f54ecb040198098c.jpg
Printing trigger image:
[array([[[ 70, 141, 143],
[ 71, 142, 146],
[ 67, 141, 144],
...,
[242, 253, 255],
[242, 253, 255],
[242, 253, 255]],
[[ 61, 135, 136],
[ 64, 135, 137],
[ 63, 134, 138],
...,
[242, 253, 255],
[242, 253, 255],
[242, 253, 255]],
[[ 57, 133, 133],
[ 63, 137, 138],
[ 65, 136, 138],
...,
[242, 253, 255],
[242, 253, 255],
[242, 253, 255]],
...,
[[246, 244, 255],
[244, 242, 253],
[244, 242, 253],
...,
[ 21, 43, 100],
[ 20, 40, 101],
[ 22, 42, 103]],
[[244, 243, 251],
[243, 241, 252],
[242, 240, 251],
...,
[ 26, 49, 103],
[ 25, 45, 104],
[ 25, 45, 106]],
[[244, 243, 251],
[243, 242, 250],
[243, 242, 250],
...,
[ 27, 48, 103],
[ 26, 45, 104],
[ 26, 44, 106]]], dtype=uint8)
array(<PIL.MpoImagePlugin.MpoImageFile image mode=RGB size=3872x2592 at 0x17D8F7434E0>,
dtype=object)]
The ouput:
KeyError Traceback (most recent call last)
<ipython-input-22-b76e704a99f8> in <module>
8 img = io.imread(url)
9 saved_path = os.path.join(saved_dir, url[-20:])
---> 10 io.imsave(saved_path, img)
~\Anaconda3\lib\site-packages\skimage\io\_io.py in imsave(fname, arr, plugin, **plugin_args)
137 if fname.lower().endswith(('.tiff', '.tif')):
138 plugin = 'tifffile'
--> 139 if is_low_contrast(arr):
140 warn('%s is a low contrast image' % fname)
141 if arr.dtype == bool:
~\Anaconda3\lib\site-packages\skimage\exposure\exposure.py in is_low_contrast(image, fraction_threshold, lower_percentile, upper_percentile, method)
501 image = rgb2gray(image)
502
--> 503 dlimits = dtype_limits(image, clip_negative=False)
504 limits = np.percentile(image, [lower_percentile, upper_percentile])
505 ratio = (limits[1] - limits[0]) / (dlimits[1] - dlimits[0])
~\Anaconda3\lib\site-packages\skimage\util\dtype.py in dtype_limits(image, clip_negative)
55 warn('The default of `clip_negative` in `skimage.util.dtype_limits` '
56 'will change to `False` in version 0.15.')
---> 57 imin, imax = dtype_range[image.dtype.type]
58 if clip_negative:
59 imin = 0
KeyError: <class 'numpy.object_'>

Edit
I reproduced your results with:
from skimage import io
url = "https://requestor-proxy.figure-eight.com/figure_eight_datasets/open-images/test/f54ecb040198098c.jpg"
img = io.imread(url)
print(img.shape)
Turns out, this actually returns two images or layers of the same image, where img[0] is the actual image you want, and img[1] is some faulty reading in Pillow (the module skimage is using to read images).
Check this issue out.
For now, some quick workaround should be fine.
if img.shape[0] == 2:
img = img[0]
Original
Could you show the URL that triggers this error? It could be your formatting on url[-20:] that adds some funky extension. Also, I'd recommend just printing img and img.shape and img.dtype to have a better idea of what's going on.

Related

Extracting the location of a specific colour in an image in Python 3.9

I would like to ask a question related to the color detection in an image in Python 3.9. I would like to detect black color at the specific x axis in the image and extract the location of the black area in the image. Could you help me how to extract the location of the black area in an image?
I can load the image and visualize it by the following code.
from PIL import Image
im =Image.open('c97dae05fd9244d4d10305b8066246psXmnlRxU59D0kJ0-0.jpeg')
im.show()
import numpy
imarray = numpy.array(im)
print(imarray)
Image.fromarray(imarray)
Some background context before I give you a solution.
Images are 3D arrays meaning the index 1 for example will be 2 arrays deep so something like this: [[[]]].
For example using numpy you can check the shape of such array using imarray.shape which should return something like (3888, 5184, 3). With this information you can see that there are 3888 arrays that contain 5184 arrays that contain 3 values.
You can maybe see a pattern occur. RGB is red, green, blue (3 values) and the third array is 3 values long which is where you will find your RGB values.
Lets take a image I had in my computer as example. I loaded it using pillow and made it into a numpy array, just like you did.
from Pill import Image
import numpy
im = Image.open('G0626494.jpg')
imarray = numpy.array(im)
Lets now print imarray:
This should print some columns and rows and RGB values, normally some from the beginning, middle and end.
array([[[ 66, 143, 185],
[ 64, 141, 183],
[ 60, 137, 179],
...,
[ 58, 96, 75],
[ 56, 94, 73],
[ 57, 95, 74]],
[[ 65, 142, 184],
[ 63, 140, 182],
[ 60, 137, 179],
...,
[ 57, 95, 74],
[ 56, 94, 73],
[ 57, 95, 74]],
[[ 63, 140, 182],
[ 62, 139, 181],
[ 59, 136, 178],
...,
[ 57, 95, 74],
[ 57, 95, 74],
[ 58, 96, 75]],
...,
[[ 80, 167, 195],
[ 80, 167, 195],
[ 82, 167, 196],
...,
[130, 190, 162],
[129, 189, 161],
[129, 189, 161]],
[[ 82, 169, 197],
[ 81, 168, 196],
[ 83, 168, 197],
...,
[128, 188, 160],
[128, 188, 160],
[128, 188, 160]],
[[ 82, 169, 197],
[ 81, 168, 196],
[ 83, 168, 197],
...,
[127, 187, 159],
[127, 187, 159],
[127, 187, 159]]], dtype=uint8)
As you can see those 3 values on the 3rd array are the RGB values of the image. How do you get them?
Lets take the first pixel as example. If you know basic array manipulation in python you probably will know this but since we know the shape is 3 this means the first pixel will be under imarray[0][0].
If we print this value we indeed get the RGB of the first pixel:
array([ 66, 143, 185], dtype=uint8)
Now how do you cycle through them. I challenge you to try this based on the past knowledge or try along this tutorial.
So if we have 2 arrays to get the RGB of the first pixel we need 2 loops right? So we can do it like this:
for row in imarray:
for column in row:
print(column)
You will now be able to see a bunch of RGB values get printed.
So lets check for black pixels now. We know black is 0, 0, 0 so we can check if any pixel is 0, 0, 0 and print it.
for row in imarray:
for column in row:
if column[0] == 0 and column[1] == 0 and column[2] == 0:
print(column)
You can also check for colors next to black but not 0, 0, 0 if you check if the column values are all the same but less then 50 for example.

Sum of positive arrays yields negative results

I try to sum together three positive arrays, however, the result yields an array that has negative values. How is this possible?
#Example of an image
img=np.array(([[[246, 240, 243],[240, 239, 239],
[243, 242, 244]],[[ 241, 240, 240],
[241, 243, 246],[ 239, 239, 239]],
[[249, 249, 250],[ 33, 33, 34],
[249, 249, 249]],[[ 33, 33, 33],
[250, 250, 249],[ 34, 34, 34]]]), dtype=np.uint8)
#Creating three positive arrays from image
#Image type converted to np.int16 as otherwise values remain between 0-255
R=abs((img[:,:,0].astype(np.int16)-255)**2)
G=abs((img[:,:,1].astype(np.int16)-255)**2)
B=abs((img[:,:,2].astype(np.int16)-255)**2)
print(R, G, B)
[[ 81 225 144]
[ 196 196 256]
[ 36 16252 36]
[16252 25 16695]] [[ 225 256 169]
[ 225 144 256]
[ 36 16252 36]
[16252 25 16695]] [[ 144 256 121]
[ 225 81 256]
[ 25 16695 36]
[16252 36 16695]]
#Adding three positive arrays together
R+G+B
array([[ 450, 737, 434],
[ 646, 421, 768],
[ 97, -16337, 108],
[-16780, 86, -15451]], dtype=int16)
I thought it had something to do with the abs() function I am applying, however, the results separately clearly show they are referenced correctly and positive?

Time series with matrix

I have a mat extension data which I want to separate every seconds values. My matrix is (7,5,2500) time series 3 dimensional matrix which want to get the values of (7,5,1) ...(7,5,2500) separately and save it
for example
array([155, 33, 129,167,189,63,35
161, 218, 6,58,36,25,3
89,63,36,25,78,95,21
78,52,36,56,25,15,68
]],
[215, 142, 235,
143, 249, 164],
[221, 71, 229,
56, 91, 120],
[236, 4, 177,
171, 105, 40])
for getting every part of this data for example this matrix
[215, 142, 235,
143, 249, 164]
what should I do?
a = [[155, 33, 129, 161, 218, 6],
[215, 142, 235, 143, 249, 164],
[221, 71, 229, 56, 91, 120],
[236, 4, 177, 171, 105, 40]]
print(a[1])
Assuming you have your data saved in a numpy array you could use slicing to extract the sub-matrices you need. Here is an example with a (3,5,3) matrix (but the example could be applied to any dimension):
A = numpy.array([[[1,1,1],
[2,2,2],
[3,3,3],
[4,4,4],
[5,5,5]],
[[11,11,11],
[21,21,21],
[31,31,31],
[41,41,41],
[51,51,51]],
[[12,12,12],
[22,22,22],
[32,32,32],
[42,42,42],
[52,52,52]]]
sub_matrix_1 = A[:,:,0]
print (sub_matrix_1)
Will produce:
[[ 1 2 3 4 5]
[11 21 31 41 51]
[12 22 32 42 52]]
EDIT: it is also possible to iterate over the array to get the 3rd dimension array:
for i in range(A.shape[-1]):
print (A[:,:,i])
# Your submatrix is A[:,:,i], you can directly manipulate it

Group pixels in an Image array, in Python [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have a numpy array - from an image - in this shape:
Arr =
array([[[ 61, 61, 61],
[ 60, 60, 60],
[ 60, 60, 60],
...,
[203, 203, 203],
[201, 201, 201],
[199, 199, 199]],
.
.
.
[[204, 204, 204],
[204, 204, 204],
[204, 204, 204],
...,
[205, 205, 205],
[206, 206, 206],
[207, 207, 207]]], dtype=uint8)
I want to work with this array in "tuples" of varying length e.g. 5 (and not just the current 3):
array([[[ 61, 61, 61, 60, 60],
[ 60, 60, 60, 60, 60],
.
.
.
Function tuple() seem to be for lists and in any case it does not offer the option to determine the length of a group of pixels. I have also tried using zip(), thus:
newArr = zip(*[Arr[i::n] for i in range(n)]). For n=5, it gives:
newArr =
[(array([[ 61, 61, 61],
[ 60, 60, 60],
[ 60, 60, 60],
...,
[203, 203, 203],
[201, 201, 201],
[199, 199, 199]], dtype=uint8), array([[ 63, 63, 63],
[ 62, 62, 62],
[ 62, 62, 62],
.
.
.
[207, 207, 207],
[209, 209, 209],
[210, 210, 210]], dtype=uint8), array([[204, 204, 204],
[204, 204, 204],
[205, 205, 205],
...,
[206, 206, 206],
[207, 207, 207],
[208, 208, 208]], dtype=uint8))]
Any way out of this? Here is the image:
The reason the values are grouped in threes is because those are the values of the color channels, either RGB, HSV or whatever the format is. Each pixel has three values, that is why you cant group them any other way. You could convert the image to grayscale with:
from PIL import Image
import numpy as np
img = Image.open('imagename')
img2 = img.convert('L')
img2_array = np.asarray(img2).copy()
That will change the value of each pixel to a single integer (0-255) and leave you with an array with the dimensions of the image itself.
EDIT:
To segment the image into five pixel groups:
seg = 5
img2_array = img2_array.tolist()
img_grouped = np.array([img2_array[0][x:x+seg] for x in range(0,len(img2_array),seg)])

Replace values in an 2d array according to neighboring values

I have an array (n,m) :
[255 100 255]
[100 255 100]
[255 100 255]
I need to create a new array like that where neigboring values are tested an if North, East, South, West are ALL equal to 100 my value is set to 100 :
[255 100 255]
[100 100 100]
[255 100 255]
I have a simple solution that loops on 1:n and 1:m but it is obviously very slow and I am wondering if there is way to do it faster.
I found several links that are talking about sliding window to compute average but i don't see how i can keep track of my indexes to create the new array.
Using strides for an efficient moving average filter
Thanks in advance for your inputs.
Assuming A as the input array, here's one approach using slicing and boolean indexing -
# Get west, north, east & south elements for [1:-1,1:-1] region of input array
W = A[1:-1,:-2]
N = A[:-2,1:-1]
E = A[1:-1,2:]
S = A[2:,1:-1]
# Check if all four arrays have 100 for that same element in that region
mask = (W == 100) & (N == 100) & (E == 100) & (S == 100)
# Use the mask to set corresponding elements in a copy version as 100s
out = A.copy()
out[1:-1,1:-1][mask] = 100
Sample run -
In [90]: A
Out[90]:
array([[220, 93, 205, 82, 23, 210, 22],
[133, 228, 100, 27, 210, 186, 246],
[196, 100, 73, 100, 86, 100, 53],
[195, 131, 100, 142, 100, 214, 100],
[247, 73, 117, 116, 24, 100, 50]])
In [91]: W = A[1:-1,:-2]
...: N = A[:-2,1:-1]
...: E = A[1:-1,2:]
...: S = A[2:,1:-1]
...: mask = (W == 100) & (N == 100) & (E == 100) & (S == 100)
...:
...: out = A.copy()
...: out[1:-1,1:-1][mask] = 100
...:
In [92]: out
Out[92]:
array([[220, 93, 205, 82, 23, 210, 22],
[133, 228, 100, 27, 210, 186, 246],
[196, 100, 100, 100, 86, 100, 53],
[195, 131, 100, 142, 100, 100, 100],
[247, 73, 117, 116, 24, 100, 50]])
Such problems are seen largely in signal-processing/image-processing domain. So, you can use 2D convolution too for an alternative solution, like so -
from scipy import signal
from scipy import ndimage
# Use a structuring elements with north, west, east and south elements as 1s
strel = ndimage.generate_binary_structure(2, 1)
# 2D Convolve to get 4s at places that are surrounded by 1s
mask = signal.convolve2d((A==100).astype(int),strel,'same')==4
# Use the mask to set corresponding elements in a copy version as 100
out = A.copy()
out[mask] = 100
Sample run -
In [119]: A
Out[119]:
array([[108, 184, 0, 176, 131, 86, 201],
[ 22, 47, 100, 78, 151, 196, 221],
[185, 100, 142, 100, 121, 100, 24],
[201, 101, 100, 138, 100, 20, 100],
[127, 227, 217, 19, 206, 100, 43]])
In [120]: strel = ndimage.generate_binary_structure(2, 1)
...: mask = signal.convolve2d((A==100).astype(int),strel,'same')==4
...:
...: out = A.copy()
...: out[mask] = 100
...:
In [121]: out
Out[121]:
array([[108, 184, 0, 176, 131, 86, 201],
[ 22, 47, 100, 78, 151, 196, 221],
[185, 100, 100, 100, 121, 100, 24],
[201, 101, 100, 138, 100, 100, 100],
[127, 227, 217, 19, 206, 100, 43]])
A more straight-forward approach would be with ndimage.binary_closing, which is exactly the intended operation of closing here. So, another alternative way to get the mask would be -
strel = ndimage.generate_binary_structure(2, 1)
mask = ndimage.binary_closing(A==100, structure=strel)

Categories