Numpy Resize Image - python

I would like to take an image and change the scale of the image, while it is a numpy array.
I would like to do it with native NumPy functions w/o PIL, cv2, SciPy etc
now I have this:
from copy import copy
import numpy as np
from scipy import misc
img = misc.face() # racoon from SciPy(np.ndarray)
img2 = copy(img) # copy of racoon, because misc.face() is Descriptor(?)
img2.shape() # (768, 1024, 3)
Which I need shape = (3072, 4096, 3)
I can do it easy with Pillow
CONVERT_IMAGE = Image.fromarray(img.astype('uint8'), 'RGB')
CONVERT_IMAGE = CONVERT_IMAGE.resize((4096, 3072), Image.NEAREST)
IMAGE_AS_ARRAY = np.asarray(CONVERT_IMAGE)
IMAGE_AS_ARRAY.shape # 3072 4096 3
but I realy need to do this only with NumPy functions w/o other libs
Can you help me ? I'm really weak in NumPy and 3D-arrays

Limited to whole integer upscaling with some scaling factor n and without actual interpolation, you could use np.repeat twice to get the described result:
import numpy as np
# Original image with shape (4, 3, 3)
img = np.random.randint(0, 255, (4, 3, 3), dtype=np.uint8)
# Scaling factor for whole integer upscaling
n = 4
# Actual upscaling (results to some image with shape (16, 12, 3)
img_up = np.repeat(np.repeat(img, n, axis=0), n, axis=1)
# Outputs
print(img[:, :, 1], '\n')
print(img_up[:, :, 1])
Here's some output:
[[148 242 171]
[247 40 152]
[151 131 198]
[ 23 185 144]]
[[148 148 148 148 242 242 242 242 171 171 171 171]
[148 148 148 148 242 242 242 242 171 171 171 171]
[148 148 148 148 242 242 242 242 171 171 171 171]
[148 148 148 148 242 242 242 242 171 171 171 171]
[247 247 247 247 40 40 40 40 152 152 152 152]
[247 247 247 247 40 40 40 40 152 152 152 152]
[247 247 247 247 40 40 40 40 152 152 152 152]
[247 247 247 247 40 40 40 40 152 152 152 152]
[151 151 151 151 131 131 131 131 198 198 198 198]
[151 151 151 151 131 131 131 131 198 198 198 198]
[151 151 151 151 131 131 131 131 198 198 198 198]
[151 151 151 151 131 131 131 131 198 198 198 198]
[ 23 23 23 23 185 185 185 185 144 144 144 144]
[ 23 23 23 23 185 185 185 185 144 144 144 144]
[ 23 23 23 23 185 185 185 185 144 144 144 144]
[ 23 23 23 23 185 185 185 185 144 144 144 144]]
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.8.5
NumPy: 1.19.2
----------------------------------------

Related

PIL image producing array of unexpected size

I am writing a program to generate photomosaics and I need the find the average RGB value of an image. I am doing this using distance and numpy as such:
def average_color(image):
"""get the average rgb color of the image"""
npimg = np.array(image)
avg = np.round(np.average(npimg,axis=(0,1)))
return avg
The problem is, for some reason once in a while it produces a numpy.float64 instead of a numpy array. I discovered that the problem came from a weird value of npimg :
[[234 232 244 236 239 240 240 243 238 242]
[237 234 235 234 230 231 235 237 240 243]
[242 239 234 243 248 249 245 238 241 243]
[246 247 246 252 255 255 252 244 248 246]
[250 251 250 254 255 255 254 247 251 249]
[252 253 253 255 255 255 255 253 253 251]
[253 253 251 254 255 255 254 249 253 251]
[252 253 250 253 255 255 253 244 252 249]
[248 245 233 244 246 246 243 228 240 242]
[240 230 225 233 233 234 227 222 224 234]]
When usually it looks like this:
[[252 228 200]
[252 228 200]
[252 228 200]
[251 227 199]
[252 228 200]
[252 228 200]
[253 229 201]
[254 230 202]
[253 230 199]
[253 230 199]]
Why does it do that and how can I solve it ( can I safely use reshape for this job?)

print each 10 numbers in line always printing the first value alone

I have this loop which print each 10 numbers in line then move to next line
for i in range(100, 201):
if i % 10 == 0:
print(i)
else:
print(i, end=" ", )
and this the result:
100
101 102 103 104 105 106 107 108 109 110
111 112 113 114 115 116 117 118 119 120
121 122 123 124 125 126 127 128 129 130
131 132 133 134 135 136 137 138 139 140
141 142 143 144 145 146 147 148 149 150
151 152 153 154 155 156 157 158 159 160
161 162 163 164 165 166 167 168 169 170
171 172 173 174 175 176 177 178 179 180
181 182 183 184 185 186 187 188 189 190
191 192 193 194 195 196 197 198 199 200
it printing first number in line alone, but the want the opposite, the last number alone, something like this
100 101 102 103 104 105 106 107 108 109
110 111 112 113 114 115 116 117 118 119
120 121 122 123 124 125 126 127 128 129
130 131 132 133 134 135 136 137 138 139
140 141 142 143 144 145 146 147 148 149
150 151 152 153 154 155 156 157 158 159
160 161 162 163 164 165 166 167 168 169
170 171 172 173 174 175 176 177 178 179
180 181 182 183 184 185 186 187 188 189
190 191 192 193 194 195 196 197 198 199
200
You have the correct code. The only thing is that you are breaking at mod 0. You should break at mod 9.
for i in range(100, 201):
if i % 10 == 9:
print(i)
else:
print(i, end=" ", )
Try this:
for i in range(100, 201):
if (i + 1) % 10 == 0:
print(i)
else:
print(i, end=" ")
Well, 100 % 10 is equals to zero.
Which means it's going to print 100 in a line, and 101 in another line.
If you want the new line to start from 100 then all you have to do is to make the statement i % 10 == 0 a false statement. So you will have to add one to the 100.
so just try this code instead
for i in range(100, 201):
if (i+1) % 10 == 0:
print(i)
else:
print(i, end=" ", )
or you could try changing i % 10 == 0 to i % 10 == 9
What I Can Say By Seeing Your Code Is That You Are Using 2 Print Statements. One Inside The If Statement And One Inside Else Statement.
So What Python Compiler Is Doing There Is Printing New Line When Each If Statement Is True.
So When Your Iterating Number%10 Will Be Zero It Will Print That Number And Add A New Line, Because After Each Print Statement Python Do So.
And As You Have end=" " in Else Statement So It Is Printing The Number In Same Line When IF Statements Are False.
So What You Can Do Is:
You Can Use if (i+1)%10: instead of i % 10 == 0:
When Your Iterating Number's(i's) One's Place Will Be 9 (i.e. 109,119,etc) The If Statement Will Be True For That One, The Number Will Be Printed On The Same Line And Will Add A New Line After That.

Python - How can I convert a 2D grayscale image to a 1D vector

I'm learning python and am trying to learn about manipulating images. I want to rescale (downscale) a 2D graysacle image to a 1D vector (array of single row/column). In my test code, when I rescale the image, the output values in the array are in decimal (float) format. But I want to rescale and keep the values in the 1D array as integers. Can someone please help/guide me?
This is my code:
#Testing Image to vector
#Importing required functionality
import skimage.io as io
import numpy as np
from skimage.transform import rescale
#read image
image=io.imread("https://www.usna.edu/Users/cs/wcbrown/courses/F14IC210/lab/l09/cat.jpg")
#print image
print (image)
#rescale to 50%
small_im = rescale(image,0.5)
#print the rescaled image
print(small_im)
#manipulate the array
x=np.array(small_im)
#convert to 1D vector
y=np.concatenate(x)
print (y)
#print each value in the 1D vector in a new line. Just to see how far it would go
for i in y:
print (i, end='\n')
A snippet of the output I get is this(it goes way further due to the loop):
[[ 8 8 9 ... 12 11 11]
[ 8 8 9 ... 12 11 11]
[ 7 7 8 ... 12 11 11]
...
[ 5 5 5 ... 98 97 96]
[ 5 5 5 ... 98 97 97]
[ 5 5 5 ... 99 98 97]]
[[0.02745098 0.02941176 0.02941176 ... 0.04509804 0.04313725 0.04313725]
[0.0254902 0.0254902 0.0254902 ... 0.04509804 0.04313725 0.04313725]
[0.0254902 0.0254902 0.0254902 ... 0.04509804 0.04313725 0.04313725]
...
[0.01960784 0.01960784 0.01960784 ... 0.38039216 0.37843137 0.37647059]
[0.01960784 0.01960784 0.01960784 ... 0.38039216 0.37843137 0.37647059]
[0.01960784 0.01960784 0.01960784 ... 0.38039216 0.38039216 0.37843137]]
[0.02745098 0.02941176 0.02941176 ... 0.38039216 0.38039216 0.37843137]
0.027450980392156862
0.029411764705882575
0.029411764705882575
0.027450980392156862
0.03137254901960784
0.03529411764705882
0.03529411764705882
0.032352941176470695
0.03039215686274498
0.02941176470588213
0.030392156862744994
0.03431372549019597
0.03529411764705882
0.0392156862745098
0.0392156862745098
0.0392156862745098
0.0392156862745098
0.0392156862745098
0.043137254901960784
After trying and googling, I've found the answer. At least, in my context, it is what I was trying to achieve.
Solution code:
#solution to converting to 1D vector
#Importing required functionality
import numpy as np
from PIL import Image
#Opening Image and resizing to 10X10 for easy viewing
image_test = np.array(Image.open('1.png').resize((10,10))) #note: I used a local image
#print image
print (image_test)
#manipulate the array
x=np.array(image_test)
#convert to 1D vector
y=np.concatenate(x)
print (y)
#print each value in the 1D vector in a new line. Just to see how far it would go
for i in y:
print (i, end='\n')
Desired sample output (due to the loop it goes further):
[[ 48 52 72 96 96 99 81 71 68 47]
[ 52 85 133 149 168 175 157 116 70 46]
[ 54 129 170 174 185 179 177 169 92 42]
[ 55 142 165 171 187 175 162 167 97 40]
[112 150 144 134 172 157 128 143 129 113]
[162 166 166 158 166 164 154 163 157 155]
[105 166 185 174 170 165 175 179 140 81]
[ 35 113 199 170 147 145 174 181 83 32]
[ 46 65 179 183 160 153 166 155 71 37]
[ 47 58 169 178 170 159 148 158 74 39]]
[ 48 52 72 96 96 99 81 71 68 47 52 85 133 149 168 175 157 116
70 46 54 129 170 174 185 179 177 169 92 42 55 142 165 171 187 175
162 167 97 40 112 150 144 134 172 157 128 143 129 113 162 166 166 158
166 164 154 163 157 155 105 166 185 174 170 165 175 179 140 81 35 113
199 170 147 145 174 181 83 32 46 65 179 183 160 153 166 155 71 37
47 58 169 178 170 159 148 158 74 39]
48
52
72
96
96
99
81
71
68
47
52
85
133
149
168
175
157
116
70
46

Python histogram has always incorrect bins

I am trying to plot a histogram in Python with plt.hist. This is the array I would like to plot:
[162 162 162 161 162 157 162 161 164 161 163 160 155 162 160 154 162 162
163 160 162 157 162 160 165 161 162 161 155 163 161 155 162 162 162 161
163 156 163 160 165 161 163 161 154 162 160 155 163 163 163 161 162 156
162 160 165 161 162 160 154 163 161 155 163 162 163 160 163 157 163 161
165 161 162 160 155 162 160 155 164 164 159 155 161 159 158 160 161 161
155 159 154 154 156 155 160 160 163 158 160 163 159 156 159 162 156 163
155 154 156 152 158 158 154 156 158 158 156 157 158 160 160 159 153 152
153 150 154 155 158 158 159 160 156 157 163 157 158 159 159 155 156 157
154 155 157 158 155 154 155 157 160 154 154 157 157 157 156 153 157 156
156 161 157 155 154 153 159 158 157 157 158 155 159 154 156 156 156 158
159 155 150 148 158 159 156 157 157 155 157 158 158 158 157 156 157 153
159 156 160 156 158 156 156 153 156 156 157 157 157 157 160 157 156 156
159 155 154 158 156 155 154 160 158 158 159 155 155 158 158 156 155 156
151 158 157 156 156 155 158 158 159 157 155 158 157 154 157 157 157 159
155 156 154 156]
And this is my easy code:
hst = plt.hist(stego_histogram , bins=256)
plt.show()
This array is constructed with some pixels of a image. Obviously, 8-bit depth image has 256 values, that is why I choosed that bins. However, as this values goes from 148 to 165, the histogram return values from this range but divided into 256 values.
I have tried to configure the histogram with other bins values (16,17,18..) but it is never printed okay. This is the histogram with bins=18:
How can I plot this histogram correctly? I just want a bar histogram of this values. Thanks.
What histogram does is just count how many times a value repeats and then plots a vertical bar for every possible value, the height of each vertical bar is the number of occurrences of that value.
If you want the full histogram between 0 and 255 then you need to specify the parameter called range in the hist call.
Otherwise you could also use the bar method from matplotlib to just show the array you have provided here.
Here is the documentation for matplot bar
I really don't know why but with bins=17 everything is plotted okay. The issue was that intervals weren't integer as you can see in the graph that I attached. I tried this bins value before but it didn't works. Sorry and thanks for your answers!
What you need is not a histogram but a bar chart for the frequencies. The frequencies can be computed using Counter. In the below answer, replace data by your actual data list.
import matplotlib.pyplot as plt
from collections import Counter
data = [162, 162, 162, 161, 162, 157, 162, 159, 155, 155, 158, 158, 156]
freqs = Counter(data)
plt.bar(freqs.keys(), freqs.values())
plt.show()
IIUC, you want something like this:
counts, bins, _ = plt.hist(data, bins=range(256))
plt.show()
Output:

Numpy 1d array subtraction - not getting expected result.

I have 2 arrays of shape (128,). I want the elementwise difference between them.
for idx, x in enumerate(test):
if idx == 0:
print (test[idx])
print()
print(library[idx])
print()
print(np.abs(np.subtract(library[idx],test[idx])))
output:
[186 3 172 80 187 120 127 172 96 213 103 107 137 119 33 53 54 113
200 78 140 234 77 94 151 64 199 218 170 73 152 73 0 5 121 42
0 106 166 80 115 220 56 66 194 187 51 132 55 73 150 83 91 204
108 58 183 0 32 240 255 55 151 255 189 153 77 89 42 176 204 170
93 117 194 195 59 204 149 55 111 255 218 48 72 171 122 163 255 155
198 179 69 173 108 0 0 176 249 214 193 255 106 116 0 47 255 255
255 255 210 175 67 0 95 120 21 158 0 72 120 255 121 208 255 0
61 255]
[189 0 178 72 177 124 123 167 81 235 110 123 139 107 39 54 34 102
195 59 156 255 66 112 161 65 180 236 181 69 142 82 0 0 152 38
0 102 146 86 117 230 59 77 220 182 44 121 63 59 146 41 92 213
146 70 184 0 0 255 255 42 165 255 245 152 114 88 63 138 255 158
96 141 221 201 47 191 179 42 156 255 237 7 136 168 133 142 254 164
236 250 56 202 141 0 0 197 255 184 212 255 108 133 0 7 255 255
255 255 243 197 74 0 50 143 24 175 0 74 101 255 121 207 255 0
146 255]
[ 3 253 6 248 246 4 252 251 241 22 7 16 2 244 6 1 236 245
251 237 16 21 245 18 10 1 237 18 11 252 246 9 0 251 31 252
0 252 236 6 2 10 3 11 26 251 249 245 8 242 252 214 1 9
38 12 1 0 224 15 0 243 14 0 56 255 37 255 21 218 51 244
3 24 27 6 244 243 30 243 45 0 19 215 64 253 11 235 255 9
38 71 243 29 33 0 0 21 6 226 19 0 2 17 0 216 0 0
0 0 33 22 7 0 211 23 3 17 0 2 237 0 0 255 0 0
85 0]
So it reads, the last array printed out is the difference between the first two arrays.
189 - 186 is 3
3 - 0 is 3 (not 253)
I must be missing something trivial.
I'd rather not zip and subtract the values as I have a ton of data.
​
Your arrays probably have dtype uint8; they cannot hold values outside the interval [0, 256), and subtracting 3 from 0 wraps around to 253. The absolute value of 253 is still 253.
Use a different dtype, or restructure your computation to avoid hitting the limits of the dtype you're using.
You can just simply subtract two numpy arrays like this, it is element-wise operation:
>test = np.array([1,2,3])
>library = np.array([1,1,1])
>np.abs(library - test)
array([0, 1, 2])

Categories

Resources