I am doing a project in which I have image of electricity meter reading. I need to extract the digits in the image.
I converted the image to a numpy array using the PIL Image function.
This is the code I typed
import numpy as np
from PIL import Image
img_data = Image.open('meter1.jpg' )
img_arr = np.array(img_data)
print(img_arr)
I got this numpy array as the output
[[[ 2 96 10]
[ 2 96 10]
[ 2 96 10]
...
[ 18 144 47]
[ 13 141 48]
[ 10 139 46]]
[[ 11 105 19]
[ 10 106 19]
[ 10 104 18]
...
[ 28 156 59]
[ 26 156 60]
[ 24 155 59]]
[[ 19 115 26]
[ 16 115 25]
[ 17 113 24]
...
[ 30 162 60]
[ 28 164 62]
[ 26 165 64]]
...
[[ 0 126 18]
[ 0 126 18]
[ 0 126 18]
...
[ 4 211 77]
[ 4 211 79]
[ 6 213 83]]
[[ 0 126 18]
[ 0 126 18]
...
[ 4 212 76]
[ 4 211 79]
[ 6 213 83]]
[[ 1 124 17]
[ 1 124 17]
[ 1 124 17]
...
[ 5 211 76]
[ 5 210 79]
[ 7 212 81]]]
How do I use this numpy array to extract the numerical values or the digits or the numbers from this image?
It is a seven segment display. Was is useful to convert the image to numpy array? Is there any other approach to do this. I have not done much of hand-on python so please help
it's better first to try doing some coding, because this way your coding skills improve. by the way, I wrote a script that save your digits into separate image files. hope it helps you in your project and improving your skills.
import numpy as np
from PIL import Image
import os
directory,filename = os.path.split(__file__)
#x = np.array([ [ [255,0,0], [0,255,0], [0,0,255] ],[ [0,0,0],[128,128,128],[2,5,200] ] ],dtype=np.uint8)
main_img = Image.open('img.jpg')
x = np.array(main_img)
print(x)
#print(x[1][1] )# x[row number][column number]
#print(x.shape[1] )# x.shape = # of rows,# of cols
data_cols = []
bg_color = x[0][0]
start = False
start_id = -1
for j in range(0,x.shape[1]):
for i in range(0,x.shape[0]):
if (x[i][j][0] < 5) and (x[i][j][2] < 10):
if not start:
start_id = j
start = True
break
if i == x.shape[0]-1:
start = False
end_id = j
if start_id>=0:
data_cols.append([start_id,end_id])
start_id=-1
print("Number of digits>",len(data_cols))
images = []
for i in range(0,len(data_cols)):
images.append(x[:,data_cols[i][0]:data_cols[i][1]])
i = 0
for im_array in images:
im = Image.fromarray(im_array,'RGB')
im.save(directory + "\\" + str(i) + ".png")
i += 1
Related
Given an array of N elements find all the subsets of array with sum equal to the target value.
I have seen all the old questions available on this site related to subset sum but none of them worked for me.
Input Format
First line of input contains an Integer N size of array
Second line contains Array elements separated by space
Target sum Value
Output Format
Print all the subarrays(indices of elements).
My Code is working fine for small inputs but it is taking very much time for N >150.
Is there any other efficient algorithm for doing this.
Please tell me how to optimize this code for larger inputs.
And here is my code
from collections import deque
class Pair:
def __init__(self, i, j, path_set):
self.i = i
self.j = j
self.path_set = path_set
def get_subsets(arr, n, value):
"""
This function appends all the possible paths in result list for the given target sum
Arguments:
arr = A list of numbers
n = number of elements in that list arr
value = Target sum for which we want to generate table
"""
# return immediately if there is no possible subset in arr whose sum is equal to value
if dp[n][value] == False:
return
queue = deque()
queue.append(Pair(n, value, set()))
while len(queue) > 0:
pair = queue.popleft()
if pair.i == 0 or pair.j == 0:
result.append(pair.path_set)
else:
exclude = dp[pair.i - 1][pair.j]
if exclude:
queue.append(Pair(pair.i-1, pair.j, pair.path_set))
if pair.j >= arr[pair.i-1]:
include = dp[pair.i - 1][pair.j - arr[pair.i -1]]
if include:
b = pair.path_set.copy()
b.add(pair.i - 1)
queue.append(Pair(pair.i - 1, pair.j-arr[pair.i-1], b))
def make_dp(arr, n, value):
"""
This function makes a table of target sum equal to the value
Arguments:
arr = A list of numbers
n = number of elements in that list arr
value = Target sum for which we want to generate table
Returns:
dp = A 2D boolean table
"""
dp = [[False for i in range(value+1)] for j in range(n+1)]
for i in range(n+1):
for j in range(value+1):
if j ==0:
dp[i][j] = True
elif i == 0:
dp[i][j] = False
else:
if dp[i-1][j]:
dp[i][j] = True
elif j >=arr[i-1]:
if dp[i-1][j-arr[i-1]]:
dp[i][j] = True
return dp
if __name__ == '__main__':
n = int(input())
arr = list(map(int, input().split()))
value = int(input())
dp = make_dp(arr, n, value)
result = []
get_subsets(arr, n, value)
print(result)
The input for which it is taking very much time:
200
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 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
200
Please optimize this code or tell me any other approach for doing the same.
Thanks in advance.
You can get this in O(n) time by creating a dictionary of cumulative sums that point to their respective index. When there exists a sum s+T for a sum s in the dictionary, you have a range that adds up to T:
from itertools import accumulate
A = list(range(1,201))
T = 200
sums = {s:i for i,s in enumerate(accumulate(A)) }
result = [ [*range(i+1,sums[s+T]+1)] for s,i in sums.items() if s+T in sums ]
print(result)
# [[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
# [37, 38, 39, 40, 41],
# [199]]
Even for 1 million values in the list, this takes less than a second.
Note that this assumes that all elements in the array are > 0.
It would possible to support zero and negative values with just a few alterations:
from itertools import accumulate
A = [*range(-10,11)]
T = 20
sums = dict()
for i,s in enumerate(accumulate(A)):
sums.setdefault(s,[]).append(i)
result = []
for cum,starts in sums.items():
if cum+T not in sums: continue
result.extend( [*range(s+1,e+1)] for s in starts
for e in sums[cum+T] if s<e )
print(A)
# [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(result)
# [[9, 10, 11, 12, 13, 14, 15, 16], [12, 13, 14, 15, 16]]
This takes 2-3 seconds on a list with 1 million values but could be longer depending on the size of the result.
You may find that using itertools and combinations is a bit more efficient. The code is also much simpler.
from itertools import chain, combinations
li = [1,2,3,4,5,6]
s=12
itr=chain.from_iterable(combinations(li, n) for n in range(len(li)+1))
result = [el for el in itr if sum(el)==s]
print(result)
Output:
[(1, 5, 6), (2, 4, 6), (3, 4, 5), (1, 2, 3, 6), (1, 2, 4, 5)]
class SubSet_Sum:
def subset_sum(self, arr,target,res=[],temp= []):
if sum(arr)==target:
if not sorted(arr) in res:
res.append(sorted(arr))
else:
for i in range(len(arr)):
temp = arr[:i]+arr[i+1:]
self.subset_sum(temp, target,res)
return res
I am writing a script that can encrypt and decrypt an image using the RSA algorithm. My public key is (7, 187) and the private key is (23,187) now the calculation for the encryption is correct like for an entry in the matrix of the image, 41 the encrypted value is 46. But when the decryption is happening it is not giving the appropriate result like for 46 it is giving 136 and for every entry of 46 in the encrypt matrix the result I am getting is 136 in the decrypt matrix. And I don't know why this is happening. When I am doing the same calculation in the python prompt(or shell) it is giving the correct answer.
In the script, I am first converting the RGB image into grayscale and then converting it to a 2d numpy array, then for each element, I am applying the RSA algo(the keys) and then saving it as an image. Then I am applying the decryption key in the encrypted matrix and then the problem is occurring. Heres the code:
from PIL import Image
import numpy as np
from pylab import *
#encryption
img1 = (Image.open('image.jpeg').convert('L'))
img1.show()
img = array((Image.open('image.jpeg').convert('L')))
a,b = img.shape #saving the no of rows and col in a tuple
print('\n\nOriginal image: ')
print(img)
print((a,b))
tup = a,b
for i in range (0, tup[0]):
for j in range (0, tup[1]):
img[i][j]= (pow(img[i][j],7)%187)
print('\n\nEncrypted image: ')
print(img)
imgOut = Image.fromarray(img)
imgOut.show()
imgOut.save('img.bmp')
#decryption
img2 = (Image.open('img.bmp'))
img2.show()
img3 = array(Image.open('img.bmp'))
print('\n\nEncrypted image: ')
print(img3)
a1,b1 = img3.shape
print((a1,b1))
tup1 = a1,b1
for i1 in range (0, tup1[0]):
for j1 in range (0, tup1[1]):
img3[i1][j1]= ((pow(img3[i1][j1], 23))%187)
print('\n\nDecrypted image: ')
print(img3)
imgOut1 = Image.fromarray(img3)
imgOut1.show()
print(type(img))
The values of the matrices:
Original image:
[[41 42 45 ... 47 41 33]
[41 43 45 ... 44 38 30]
[41 42 46 ... 41 36 30]
...
[43 43 44 ... 56 56 55]
[45 44 45 ... 55 55 54]
[46 46 46 ... 53 54 54]]
Encrypted image:
[[ 46 15 122 ... 174 46 33]
[ 46 87 122 ... 22 47 123]
[ 46 15 7 ... 46 9 123]
...
[ 87 87 22 ... 78 78 132]
[122 22 122 ... 132 132 164]
[ 7 7 7 ... 26 164 164]]
Decrypted image:
[[136 70 24 ... 178 136 164]
[136 111 24 ... 146 141 88]
[136 70 96 ... 136 100 88]
...
[111 111 146 ... 140 140 1]
[ 24 146 24 ... 1 1 81]
[ 96 96 96 ... 52 81 81]]
Any help will be greatly appreciated. Thank You.
I think you will get on better using the 3rd parameter to the pow() function which does the modulus internally for you.
Here is a little example without the complexity of loading images - just imagine it is a greyscale gradient from black to white.
# Make single row greyscale gradient from 0..255
img = [ x for x in range(256) ]
# Create encrypted version
enc = [ pow(x,7,187) for x in img ]
# Decrypt back to plaintext
dec = [ pow(x,23,187) for x in enc ]
It seems to decrypt back into the original values from 0..187, where it goes wrong - presumably because of overflow? Maybe someone cleverer than me will be able to explain that - please add comment for me if you know!
I have a function like:
def calcChromaFromPixel(red, green, blue):
r = int(red)
g = int(green)
b = int(blue)
return math.sqrt(math.pow(r - g, 2) +
math.pow(r - b, 2) +
math.pow(g - b, 2))
and I have an RGB Image, which is already converted into an numpy array with a shape like [width, height, 3], where 3 are the color channels.
What I want to do is to apply the method to every pixel and build the mean from the result. I already have done the obvious thing and iterated over the array with two loops, but that seems to be a really slow thing to do... Is there a faster and prettier way to do that?!
Thanks :)
Code:
import math
import numpy as np
np.random.seed(1)
# FAKE-DATA
img = np.random.randint(0,255,size=(4,4,3))
print(img)
# LOOP APPROACH
def calcChromaFromPixel(red, green, blue):
r = int(red)
g = int(green)
b = int(blue)
return math.sqrt(math.pow(r - g, 2) +
math.pow(r - b, 2) +
math.pow(g - b, 2))
bla = np.zeros(img.shape[:2])
for a in range(img.shape[0]):
for b in range(img.shape[1]):
bla[a,b] = calcChromaFromPixel(*img[a,b])
print('loop')
print(bla)
# VECTORIZED APPROACH
print('vectorized')
res = np.linalg.norm(np.stack(
(img[:,:,0] - img[:,:,1],
img[:,:,0] - img[:,:,2],
img[:,:,1] - img[:,:,2])), axis=0)
print(res)
Out:
[[[ 37 235 140]
[ 72 137 203]
[133 79 192]
[144 129 204]]
[[ 71 237 252]
[134 25 178]
[ 20 254 101]
[146 212 139]]
[[252 234 156]
[157 142 50]
[ 68 215 215]
[233 241 247]]
[[222 96 86]
[141 233 137]
[ 7 63 61]
[ 22 57 1]]]
loop
[[ 242.56545508 160.44313634 138.44132331 97.21111048]
[ 246.05283985 192.94040531 291.07730932 98.66103588]
[ 124.99599994 141.90842117 207.88939367 17.20465053]
[ 185.66636744 133.02631319 77.82030583 69.29646456]]
vectorized
[[ 242.56545508 160.44313634 138.44132331 97.21111048]
[ 246.05283985 192.94040531 291.07730932 98.66103588]
[ 124.99599994 141.90842117 207.88939367 17.20465053]
[ 185.66636744 133.02631319 77.82030583 69.29646456]]
I'm trying to reshape a numpy array as:
data3 = data3.reshape((data3.shape[0], 28, 28))
where data3 is:
[[54 68 66 ..., 83 72 58]
[63 63 63 ..., 51 51 51]
[41 45 80 ..., 44 46 81]
...,
[58 60 61 ..., 75 75 81]
[56 58 59 ..., 72 75 80]
[ 4 4 4 ..., 8 8 8]]
data3.shape is (52, 2352 )
But I keep getting the following error:
ValueError: cannot reshape array of size 122304 into shape (52,28,28)
Exception TypeError: TypeError("'NoneType' object is not callable",) in <function _remove at 0x10b6477d0> ignored
What is happening and how to fix this error?
UPDATE:
I'm doing this to obtain data3 that is being used above:
def image_to_feature_vector(image, size=(28, 28)):
return cv2.resize(image, size).flatten()
data3 = np.array([image_to_feature_vector(cv2.imread(imagePath)) for imagePath in imagePaths])
imagePaths contains paths to all the images in my dataset. I actually want to convert the data3 to a flat list of 784-dim vectors, however the
image_to_feature_vector
function converts it to a 3072-dim vector!!
You can reshape the numpy matrix arrays such that before(a x b x c..n) = after(a x b x c..n). i.e the total elements in the matrix should be same as before, In your case, you can transform it such that transformed data3
has shape (156, 28, 28) or simply :-
import numpy as np
data3 = np.arange(122304).reshape(52, 2352 )
data3 = data3.reshape((data3.shape[0]*3, 28, 28))
print(data3.shape)
Output is of the form
[[[ 0 1 2 ..., 25 26 27]
[ 28 29 30 ..., 53 54 55]
[ 56 57 58 ..., 81 82 83]
...,
[ 700 701 702 ..., 725 726 727]
[ 728 729 730 ..., 753 754 755]
[ 756 757 758 ..., 781 782 783]]
...,
[122248 122249 122250 ..., 122273 122274 122275]
[122276 122277 122278 ..., 122301 122302 122303]]]
First, your input image's number of elements should match the number of elements in the desired feature vector.
Assuming the above is satisfied, the below should work:
# Reading all the images to a one numpy array. Paths of the images are in the imagePaths
data = np.array([np.array(cv2.imread(imagePaths[i])) for i in range(len(imagePaths))])
# This will contain the an array of feature vectors of the images
features = data.flatten().reshape(1, 784)
I have an image where some color channels in the pixels have a value of zero (ie 255, 146, 0). I want to be able to change any value equal to zero in the array to a different value, but I do not know how to access these values. Any help with this?
This is the image array:
[[[ 76 163 168]
[109 166 168]
[173 172 167]
...,
[ 83 182 144]
[ 78 172 134]
[ 82 150 131]]
[[ 51 151 168]
[ 99 157 171]
[173 195 159]
...,
[ 56 165 144]
[ 25 198 125]
[ 35 185 121]]
[[ 76 163 121]
[112 147 120]
[175 151 118]
...,
[ 57 162 159]
[ 36 185 132]
[ 32 194 97]]
...,
[[ 78 189 126]
[ 68 173 129]
[ 58 171 150]
...,
[ 41 188 163]
[ 34 176 126]
[ 35 176 102]]
[[131 155 161]
[101 141 161]
[ 42 151 177]
...,
[ 56 178 122]
[ 45 192 114]
[ 46 184 112]]
[[130 157 185]
[ 83 141 185]
[ 42 158 185]
...,
[ 63 187 88]
[ 45 194 102]
[ 45 184 129]]]
Use masking -
img[(img==zero_val).all(-1)] = new_val
, where zero_val is the zero color and new_val is the new color to be assigned at those places where we have zero colored pixels.
Sample run -
# Random image array
In [112]: img = np.random.randint(0,255,(4,5,3))
# Define sample zero valued and new valued arrays
In [113]: zero_val = [255,146,0]
...: new_val = [255,255,255]
...:
# Set two random points/pixels to be zero valued
In [114]: img[0,2] = zero_val
In [115]: img[2,3] = zero_val
# Use proposed approach
In [116]: img[(img==zero_val).all(-1)] = new_val
# Verify that new values have been assigned
In [117]: img[0,2]
Out[117]: array([255, 255, 255])
In [118]: img[2,3]
Out[118]: array([255, 255, 255])