I need the orignal image once again but its returning greyscale
my teacher said do colormap at the beginning and said that it happens in matlab. so i want to do similar task in python too
Here is my code have a look
please help
ENCRYPTION:
import numpy as np
from PIL import Image
x = Image.open('1.jpg', 'r')
x = x.convert('L')
y = np.asarray(x.getdata(), dtype=np.int).reshape((x.size[1], x.size[0]))#changed image to matrix getdata for matrix value # dtype is int type reshape used to break 1d array into 2d array
y = np.asarray(y, dtype=np.uint8)#if values still in range 0-255!
#print(y)
z = y
w = Image.fromarray(y, mode='L')
w.save('grey_scale.bmp')
for i in range(len(z)):
for j in range(len(z[i])):
a = z[i][j]
p = int(bin(a)[2:])
p = '%08d' % p
p = p[::-1]
z[i][j] = int(p, 2)
#print(z)
C = Image.fromarray(z)
C.save('decryption.bmp')
print("DONE")
DECRYPTION:
import numpy as np
from PIL import Image
x = Image.open('decryption.bmp', 'r')
y = np.asarray(x.getdata(), dtype=np.int).reshape((x.size[1], x.size[0]))#changed image to matrix getdata for matrix value
#print(y) # dtype is int type reshape used to break 1d array into 2d array
y = np.asarray(y, dtype=np.uint8)#if values still in range 0-255!
#print(y)
z = y
for i in range(len(z)):
for j in range(len(z[i])):
a = z[i][j]
p = int(bin(a)[2:])
p = '%08d' % p
p = p[::-1]
z[i][j] = int(p, 2)
#print(z)
C = Image.fromarray(z)
C.save('Final.bmp')
print("DONE")
I think(?) what you're looking for is a Colour Mapping function like:
def create_colourmap(colour, grey):
c_map = numpy.zeros((256,4), dtype=numpy.float64)
for i in range(colour.shape[0]):
for j in range(colour.shape[1]):
tone = grey[i,j]
c_map[tone,3] +=1
count = c_map[tone, 3]
c_map[tone,:3] = (c_map[tone,:3] * (count-1) + colour[i,j])/count
return c_map.astype(numpy.uint8)[:,:3]
Which would give you ONE colour value for each Greyscale value (or Tone).
Your 'bit reversal' procedure could be simplified by another function:
def reverse_bits(arr):
for i in range(arr.shape[0]):
for j in range(arr.shape[1]):
arr[i][j] = int('{0:08b}'.format(arr[i][j])[::-1], 2)
return arr
Putting this all together, your encrypt function would be:
def encrypt(infile, outfile):
with Image.open(infile, 'r') as colour_img:
colour_arr = numpy.array(colour_img)
grey_img = colour_img.convert('L')
grey_arr = numpy.array(grey_img)
c_map = create_colourmap(colour_arr, grey_arr)
with Image.fromarray(c_map) as cmap_img:
cmap_img.save(outfile[:-4]+'_cmap.bmp')
grey_arr = reverse_bits(grey_arr)
with Image.fromarray(grey_arr) as c:
c.save(outfile)
print("Encryption DONE")
And your decrypt function:
def decrypt(infile, outfile):
with Image.open(infile, 'r') as x:
y = numpy.array(x)
y = reverse_bits(y)
colour_arr = numpy.zeros((y.shape[0], y.shape[1], 3), dtype=numpy.uint8)
with Image.open(infile[:-4]+'_cmap.bmp') as cmap_img:
cmap = numpy.array(cmap_img)
for i in range(256):
colour_arr[y==i] = cmap[i]
with Image.fromarray(colour_arr) as c:
c.save(outfile)
print("Decryption DONE")
You'll notice that the Colour Mapping will not completely restore the image colour, but will give the image some hue. I don't know what your assignment is about, but you may want to send the Colour Map along with the encrypted image, or give them another image with similar colouring.
I hope this helps you, but you will need to lean how this works, and comment where necessary to explain whats going on.
Good luck!
Related
I'm looking for a way to modify my code to convert the RGB pixel data into hexadecimal pixel data. Such as converting 37, 4, 201 to #2504C9. Code attached, if anyone knows how to do this, I'd really appreciate it! I've tried several methods from here but so far haven't been able to find much of anything that works.
from PIL import Image
import sys
im = Image.open(r"C:\Users\AChri\Desktop\boio.png")
px = im.load()
w, h = im.size
x = 0
y= 0
while True:
if x >= w:
x = 0
y= y+1
else:
if y >= h:
print('Done!')
sys.exit()
else:
val = px[x, y]
print(px[x, y])
x = x+1
In px[x,y] you have a tuple (R, G, B), to print it as hex you can just do the following:
print("#{:02X}{:02X}{:02X}".format(*px[x,y]))
Or, to adapt it to your code:
val = "#{:02X}{:02X}{:02X}".format(*px[x,y])
print(val)
I am trying to write a program which fades an image in radial direction. which means as we move away from the centre of the image, the pixels fade to black. For this, I have written five different functions:
center: returns coordinate pair (center_y, center_x) of the image center.
radial_distance: returns for image with width w and height h an array with shape (h,w), where the number at index (i,j) gives the euclidean distance from the point (i,j) to the center of the image.
scale: returns a copy of the array 'a' (or image) with its elements scaled to be in the given range.
radial_mask: takes an image as a parameter and returns an array with same height and width filled with values between 0.0 and 1.0.
radial_fade: returns the image multiplied by its radial mask.
The program is:
import numpy as np
import matplotlib.pyplot as plt
def center(a):
y, x = a.shape[:2]
return ((y-1)/2,(x-1)/2) # note the order: (center_y, center_x)
def radial_distance(b):
h, w = b.shape[:2]
y, x = center(b)
o = b[:h,:w,0]
for i in range(h):
for j in range(w):
o[i,j] = np.sqrt((y-i)**2 + (x-j)**2)
return o
def scale(c, tmin=0.0, tmax=1.0):
"""Returns a copy of array 'a' with its values scaled to be in the range
[tmin,tmax]."""
mini, maxi = c.min(), c.max()
if maxi == 0:
return 0
else:
m = (tmax - tmin)/(maxi - mini)
f = tmin - m*mini
return c*m + f
def radial_mask(d):
f = radial_distance(d)
g = scale(f, tmin=0.0, tmax=1.0)
# f = g[:,:,0]
n = 1.0 - g
return n
def radial_fade(l):
f, g = l.shape[:2]
q = l[:f,:g,0]
return q * radial_mask(l)
image = plt.imread("src/painting.png")
fig, ax = plt.subplots(3)
masked = radial_mask(ima)
faded = radial_fade(ima)
ax[0].imshow(ima)
ax[1].imshow(masked)
ax[2].imshow(faded)
plt.show()
there is something wrong somewhere in the code as it does not do the expected job.
One problem is that in
o = b[:h,:w,0]
you're using the same precision as the image that may be integers (e.h. uint8).
You should use for example
o = np.zeros((h, w), np.float32)
I'm trying to find a way to get an image that would show the distance (difference of values) between points of two surfaces (point clouds). I want an image that would have a color scale which would show real life distance values. I'm new to this, so it might seem stupid to someone. Thank you for help
Plt.ismhow does give me a result and while it does seem to show difference, its not representitive enough.
import numpy as np
import matplotlib.pyplot as plt
def readNXYZfile(filename):
A = np.zeros((3000,3000),np.float32)
crs = open(filename, "r")
for i,columns in enumerate( raw.strip().split() for raw in crs ):
for j in range(len(columns)):
A[j,i] = np.float32(columns[j])
A = A[0:j, 0:i]
A = np.transpose(A)
X = A[:,0:int(j/3)]
Y = A[:,int(j/3+1):int(2*j/3)]
Z = A[:,int(2*j/3+1):j]
return [X,Y,Z]
filename1 = "D:\\"
filename2 = "D:\\"
[X1,Y1,Z1] = readNXYZfile(filename1)
[X2,Y2,Z2] = readNXYZfile(filename2)
Z1[Z1 < -9000] = float('nan')
Z2[Z2 < -9000] = float('nan')
B = Z1 - Z2
plt.imshow(B)
plt.show()
Can you pls explain how to create a matrix in python to be created in object datatype. My code :
w, h = 8, 5;
Matrix = ([[0 for x in range(w)] for y in range(h)],dtype=object)
gives a syntax error. I tried various other ways. But still none of them working.
Thanks a lot
In your code the Matrix line tries to create a tuple, however you are giving it an expression dtype=object.
Matrix = ([[0 for x in range(w)] for y in range(h)],dtype=object)
The line reads: Set matrix to the tuple (2D array, dtype=object). However, the second part cannot be set. You can create the matrix as follows:
Matrix = [[0 for x in range(w)] for y in range(h)]
Or if you would like to have a numpy array with dtype object:
import numpy as np
Matrix = np.array([[0 for x in range(w)] for y in range(h)], dtype=object)
Or even more clean:
import numpy as np
Matrix = np.zeros((h, w), dtype=object)
Let me present you two options using numpy module and loops.
import numpy as np
print("Using numpy module:")
x = np.array([1,5,2])
y = np.array([7,4,1])
sum = x + y
subtract = x - y
mult = x * y
div = x / y
print("Sum: {}".format(sum))
print("Subtraction: {}".format(subtract))
print("Multiplication: {}".format(mult))
print("Division: {}".format(div))
print("----------------------------------------")
print("Using for loops:")
x = [1,5,2]
y = [7,4,1]
sum = []
subtract = []
mult =[]
div = []
for i,j in zip(x,y):
sum.append(i+j)
subtract.append(i-j)
mult.append(i*j)
div.append(i/j)
print(sum)
print(subtract)
print(mult)
print(div)
My aim is to find the color of main object in a frame/image. In my case image is always of same type. For example News reporter(human) in Forest or News reporter in Animal farm.The position of news reporter is also same.What is the simple solution to find out the dominant colour of the main object(News Reporter)
Any help is welcome.Thanks
EDIT Code added
import cv2
from collections import namedtuple
from math import sqrt
import random
import webcolors
try:
import Image
except ImportError:
from PIL import Image
Point = namedtuple('Point', ('coords', 'n', 'ct'))
Cluster = namedtuple('Cluster', ('points', 'center', 'n'))
def get_points(img):
points = []
w, h = img.size
for count, color in img.getcolors(w * h):
points.append(Point(color, 3, count))
return points
rtoh = lambda rgb: '#%s' % ''.join(('%02x' % p for p in rgb))
def colorz(filename, n=3):
img = Image.open(filename)
img.thumbnail((200, 200))
w, h = img.size
points = get_points(img)
clusters = kmeans(points, n, 1)
rgbs = [map(int, c.center.coords) for c in clusters]
return map(rtoh, rgbs)
def euclidean(p1, p2):
return sqrt(sum([
(p1.coords[i] - p2.coords[i]) ** 2 for i in range(p1.n)
]))
def calculate_center(points, n):
vals = [0.0 for i in range(n)]
plen = 0
for p in points:
plen += p.ct
for i in range(n):
vals[i] += (p.coords[i] * p.ct)
return Point([(v / plen) for v in vals], n, 1)
def kmeans(points, k, min_diff):
clusters = [Cluster([p], p, p.n) for p in random.sample(points, k)]
while 1:
plists = [[] for i in range(k)]
for p in points:
smallest_distance = float('Inf')
for i in range(k):
distance = euclidean(p, clusters[i].center)
if distance < smallest_distance:
smallest_distance = distance
idx = i
plists[idx].append(p)
diff = 0
for i in range(k):
old = clusters[i]
center = calculate_center(plists[i], old.n)
new = Cluster(plists[i], center, old.n)
clusters[i] = new
diff = max(diff, euclidean(old.center, new.center))
if diff < min_diff:
break
return clusters
def main():
img = cv2.imread('d:/Emmanu/project-data/b1.jpg')
res=cv2.resize(img,(400,300))
crop_img = res[100:200, 150:250]
cv2.imwrite("d:/Emmanu/project-data/color-test.jpg", crop_img)
g= colorz('d:/Emmanu/project-data/color-test.jpg',1)
k=g[0]
print k
f=webcolors.hex_to_rgb(k)
print webcolors.rgb_to_name(f, spec='css3')
if __name__ == '__main__':main()
The problem is this returns the major color in the whole image not the main object
If your taking the colour of whole image,in most cases you will get wrong answer since background is more.If your image size is fixed and you are sure about object's position The most simple solution is Crop the image at where you expect the object.In most cases it will work.
In order to crop
import cv2
img = cv2.imread("'d:/Emmanu/project-data/b1.jpg'")
crop_img = img[200:400, 100:300] # Crop from x, y, w, h -> 100, 200, 300, 400
# NOTE: its img[y: y + h, x: x + w] and *not* img[x: x + w, y: y + h]
cv2.imshow("cropped", crop_img)
cv2.waitKey(0)
Now give this crop_image as input to your code.And in most cases it will give correct solution.There is nothing more simple that this.I think this will help.