I want to manipulate RGB bands in a TIFF file and output the grayscale map on matplotlib. So far I have this code, but I couldn't get it on grayscale:
import scipy as N
import gdal
import sys
import matplotlib.pyplot as pyplot
tif = gdal.Open('filename.tif')
band1 = tif.GetRasterBand(1)
band2 = tif.GetRasterBand(2)
band3 = tif.GetRasterBand(3)
red = band1.ReadAsArray()
green = band2.ReadAsArray()
blue = band3.ReadAsArray()
gray = (0.299*red + 0.587*green + 0.114*blue)
pyplot.figure()
pyplot.imshow(gray)
pylab.show()
And these are the arrays:
[[255 255 255 ..., 237 237 251]
[255 255 255 ..., 237 237 251]
[255 255 255 ..., 237 237 251]
...,
[237 237 237 ..., 237 237 251]
[237 237 237 ..., 237 237 251]
[242 242 242 ..., 242 242 252]]
[[255 255 255 ..., 239 239 251]
[255 255 255 ..., 239 239 251]
[255 255 255 ..., 239 239 251]
...,
[239 239 239 ..., 239 239 251]
[239 239 239 ..., 239 239 251]
[243 243 243 ..., 243 243 252]]
[[255 255 255 ..., 234 234 250]
[255 255 255 ..., 234 234 250]
[255 255 255 ..., 234 234 250]
...,
[234 234 234 ..., 234 234 250]
[234 234 234 ..., 234 234 250]
[239 239 239 ..., 239 239 251]]
Any idea how can I fix this?
I don't have gdal installed, but a similar approach using PIL looks like this:
import numpy as np
import Image
import matplotlib.pyplot as pyplot
img = Image.open("/Users/travis/Desktop/new_zealand.tif")
img.getdata()
r, g, b = img.split()
ra = np.array(r)
ga = np.array(g)
ba = np.array(b)
gray = (0.299*ra + 0.587*ga + 0.114*ba)
pyplot.figure()
pyplot.imshow(img)
pyplot.figure()
pyplot.imshow(gray)
pyplot.figure()
pyplot.imshow(gray, cmap="gray")
It may be a simple matter of setting the color map to something besides the default ("jet") to get what you want, but I'm not sure what you're seeing.
Here are the images that are generated (don't ask me why the original is upside-down -- not sure what causes that):
Related
I have an image(2D array) with 3 color channels. Something like this:
[[[128 197 254]
[128 197 254]
[128 197 254]
...
[182 244 255]
[182 244 255]
[182 244 255]]
[[128 197 254]
[128 197 254]
[128 197 254]
...
[182 244 255]
[182 244 255]
[182 244 255]]
[[128 197 254]
[128 197 254]
[128 197 254]
...
[182 244 255]
[182 244 255]
[182 244 255]]
...
[[128 197 254]
[128 197 254]
[128 197 254]
...
[182 244 255]
[182 244 255]
[182 244 255]]
[[128 197 254]
[128 197 254]
[128 197 254]
...
[182 244 255]
[182 244 255]
[182 244 255]]
[[128 197 254]
[128 197 254]
[128 197 254]
...
[182 244 255]
[182 244 255]
[182 244 255]]]
I want to get the indexes of the colors that are [255, 255, 255] for example. I tried using np.where() or np.argwhere(), but it compared values not arrays. What is the fastest and most efficient way to do it?
IIUC, you may use np.nonzero
np.nonzero((arr==255).all(axis=2))
That will return a tuple of arrays, which represent the indexes. If you do
arr[ind]
where ind is the return from the first expr, you may access/modify all rows with all 255.
A numpy way to do this with np.where would be
import numpy as np
# Generating an example array
width = 100
height = 100
channels = 3
img = np.random.rand(width, height, channels) * 255
# Defining the three value channels
r=0
g=1
b=2
# Defining the query values for the channels, here [255, 255, 255]
r_query = 255
g_query = 255
b_query = 255
# Print a 2D array with the coordinates of the white pixels
print(np.where((img[:,:,r] == r_query) & (img[:,:,g] == g_query) & (img[:,:,b] == b_query)))
This gives you a 2D-Array with the coordinates of the white pixels [255, 255, 255] in your original array (image).
Note: Another way would be using OpenCV
mask = cv2.inRange(img, [255, 255, 255], [255, 255, 255])
output = cv2.bitwise_and(img, img, mask = mask)
I have an image dataset with a string type label name. When I split the data using test_train_split of sklearn library, it converts the label to np.array type. Is there a way to get back the original string type label name?
The below code splits a data to train and test:
imgs, y = load_images()
train_img,ytrain_img,test_img,ytest_img = train_test_split(imgs,y, test_size=0.2, random_state=1)
If I print y, it gives me the label name but if I print the splitted label value it give an array:
for k in y:
print(k)
break
for k in ytrain_img:
print(k)
break
Output:
001.Affenpinscher
[[[ 97 180 165]
[ 93 174 159]
[ 91 169 152]
...
[[ 88 171 156]
[ 88 170 152]
[ 84 162 145]
...
[130 209 222]
[142 220 233]
[152 230 243]]
[[ 99 181 163]
[ 98 178 161]
[ 92 167 151]
...
[130 212 224]
[137 216 229]
[143 222 235]]
...
[[ 85 147 158]
[ 85 147 158]
[111 173 184]
...
[227 237 244]
[236 248 250]
[234 248 247]]
[[ 94 154 166]
[ 96 156 168]
[133 194 204]
...
[226 238 244]
[237 249 253]
[237 252 254]]
...
[228 240 246]
[238 252 255]
[241 255 255]]]
Is there a way to convert back the array to the original label name?
No, you are inferring the output of train_test_split wrong.
train_test_split works in this way:
A_train, A_test, B_train, B_test, C_train, C_test ...
= train_test_split(A, B, C ..., test_size=0.2)
You can give as many arrays to split. For each given array, it will provide the train and test split first, then do the same for next array, then third array and so on..
So in your case actually it is:
train_img, test_img, ytrain_img, ytest_img = train_test_split(imgs, y,
test_size=0.2,
random_state=1)
But you are then mixing up the names of the output and using them wrong.
My original dataset is 7049 images(96x96) with following format:
train_x.shape= (7049,)
train_x[:3]
0 238 236 237 238 240 240 239 241 241 243 240 23...
1 219 215 204 196 204 211 212 200 180 168 178 19...
2 144 142 159 180 188 188 184 180 167 132 84 59 ...
Name: Image, dtype: object
I want to split image-string into 96x96 and get the (7049,96,96) array.
I try this method:
def split_reshape(row):
return np.array(row.split(' ')).reshape(96,96)
result = train_x.apply(split_reshape)
Then I still got result.shape=(7049,)
How to reshape to (7049,96,96) ?
Demo:
Source Series:
In [129]: train_X
Out[129]:
0 238 236 237 238 240 240 239 241 241
1 219 215 204 196 204 211 212 200 180
2 144 142 159 180 188 188 184 180 167
Name: 1, dtype: object
In [130]: type(train_X)
Out[130]: pandas.core.series.Series
In [131]: train_X.shape
Out[131]: (3,)
Solution:
In [132]: X = train_X.str \
.split(expand=True) \
.astype(np.int16) \
.values.reshape(len(train_X), 3, 3)
In [133]: X
Out[133]:
array([[[238, 236, 237],
[238, 240, 240],
[239, 241, 241]],
[[219, 215, 204],
[196, 204, 211],
[212, 200, 180]],
[[144, 142, 159],
[180, 188, 188],
[184, 180, 167]]], dtype=int16)
In [134]: X.shape
Out[134]: (3, 3, 3)
How can I load the RGB matrix of an image. Basically, if I have a 224x224 image(grayscale), I need it's RGB matrix so I want a 224x224 matrix consisting of 3 element tuples. I have tried:
f="/path/to/grayscale/image"
image = Image.open(f)
new_width = 224
new_height = 224
im = image.resize((new_width, new_height), Image.ANTIALIAS)
im=np.array(im)
print(im)
and it prints:
[[195 195 195 ..., 101 104 105]
[195 195 195 ..., 102 105 106]
[194 194 194 ..., 104 109 111]
...,
[137 138 140 ..., 209 207 206]
[133 134 136 ..., 209 207 206]
[132 133 135 ..., 209 207 206]]
After some testing, I realised that it was because of the image being grayscale. How can I load the RGB matrix of a grayscale image?
I am not proficien in PIL, but it looks there is an image.Convert("RGB") method that may or may not work, so give it a try.
However, if your intention is to continue using np.array then the following will work:
im=np.array(im)
imRGB = np.repeat(im[:, :, np.newaxis], 3, axis=2)
Basically it repeats the input np.array into a 3rd new axis, 3 times.
imRGB[:,:,0] is the Red channel
imRGB[:,:,1] is the Green channel
imRGB[:,:,2] is the Blue channel
I'm writing a simple picture editor. It uses PPM files. From what I can tell, I feel like my code should work. However, I get this error
Traceback (most recent call last):
File "/home/zach/Downloads/piceditor (1).py", line 84, in <module>
main()
File "/home/zach/Downloads/piceditor (1).py", line 69, in main
image = Image(Point(100,100), filename)
File "/home/zach/Downloads/graphics.py", line 770, in __init__
self.img = tk.PhotoImage(file=pixmap[0], master=_root)
File "/usr/lib/python3.1/tkinter/__init__.py", line 3272, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "/usr/lib/python3.1/tkinter/__init__.py", line 3228, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize data in image file "pig.ppm"
My code looks like this
def main():
print("Image Editor")
print()
filename = input("name of image file: ")
print()
with open(filename) as f:
formatind = f.readline()
width, height = [int(x) for x in f.readline().split()]
colordepth = f.readline()
array = []
for line in f:
array.append([int(x) for x in line.split()])
win = GraphWin("Image Editor!", width, height)
image = Image(Point(100,100), filename)
Display(image, array, width, height, win)
inf.close()
win.getMouse()
win.close()
main()
And my Display function looks like this
def Display(image, array, width, height, win):
for i in range(width):
for j in range(0, height, 3):
colors = color_rgb(array[i][j], array[i][j+1], array[i][j+2])
image.setPixel(i, j, colors)
image.draw(win)
return
This is the ppm file i'm using
P3
6 8
255
249 249 249 255 255 255 250 250 250 255 255 255 250 250 250 250 250 250 254 255 255 251 255 255
249 251 255 253 249 255 255 248 255 255 234 255 255 242 255 255 245 253 255 246 243 255 253 241
255 255 237 255 255 237 252 255 241 249 255 246 249 255 253 254 255 255 255 252 255 255 248 241
255 251 239 254 247 241 252 254 253 252 255 255 251 255 255 242 242 242 255 255 255 241 241 241
0 0 0 0 0 0 4 4 4 20 20 20 236 236 236 252 252 252 254 255 253 248 255 250
0 0 0 0 0 0 4 4 4 20 20 20 236 236 236 252 252 252 254 255 253 248 255 250
I cannot for the life of me figure out why it won't recognize the data in the file.
Any help would be great. Thanks
Why don't you use the PIL library? In the documents it claims that it can work with PPM files. However I am not familiar with working with PPM files with PIL.
Example: Opening a a PPM file, creating an object from the file that then can be used to edit the file.