Python Error With PutPixel - python

So im working on project that takes input from a text document and converts it into a image. But for some reason the debugger keeps giving this error message
IndexError: image index out of range
Here is the code
f1 = open(argv[1], "r")
f2 = str(f1.read())
farr = list(f2)
size1 = len(farr)
size2 = input("Size:")
size = width, height = int(size2), int(size2);
size1 + 1
#MAKING THE IMAGE
img = Image.new('RGB', size, "white" )
map = img.load()
print(map[0,0])
Rw,Gw,Bw = [255,255,255]
Rb,Gb,Bb = [0,0,0]
def Converter(num,x,y):
while int(size1) != int(num):
if farr[num - 1: + int(num)] == ["0"]:
img.putpixel((x,y), (Rw,Gw,Bw))
x = x + 1
elif farr[num -1: + int(num)] == ["1"]:
img.putpixel((x,y), (Rb,Gb,Bb))
x = x + 1
elif farr[num -1: + int(num)] == [" "]:
y = y + 1
else:
print("nothing")
num = num + 1
Converter(1,1,1)
img.show()

Put gloabl x and global y in the converter function and it fixes everything.

Related

How to use multiprocessing in Python for for loop?

I'm new to Python and multiprocessing, I would like to speed up my current code processing speed as it takes around 8 mins for 80 images. I only show 1 image for this code for reference purpose. I got into know that multiprocessing helps on this and gave it a try but somehow not working as what I expected.
import numpy as np
import cv2
import time
import os
import multiprocessing
img = cv2.imread("C://Users/jason/Desktop/test.bmp")
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_,blackMask = cv2.threshold(gry, 0, 255, cv2.THRESH_BINARY_INV)
x1 = []
y1 = []
def verticle(mask, y, x):
vertiPixel = 0
while(y < mask.shape[0]):
if (y + 1) == mask.shape[0]:
break
else:
if(mask[y + 1][x] == 255):
vertiPixel += 1
y += 1
else:
break
y1.append(vertiPixel)
def horizontal(mask, y, x):
horiPixel = 0
while(x < mask.shape[1]):
if (x + 1) == mask.shape[1]:
break
else:
if(mask[y][x + 1] == 255):
horiPixel += 1
x += 1
else:
break
x1.append(horiPixel)
def mask(mask):
for y in range (mask.shape[0]):
for x in range (mask.shape[1]):
if(mask[y][x] == 255):
verticle(mask, y, x)
horizontal(mask, y, x)
mask(blackMask)
print(np.average(x1), np.average(y1))
This is what I tried to work on my side. Although it's not working, added pool class for multiprocessing but getting None result.
import numpy as np
import cv2
import time
import os
from multiprocessing import Pool
folderDir = "C://Users/ruler/Desktop/testseg/"
total = []
with open('readme.txt', 'w') as f:
count = 0
for allImages in os.listdir(folderDir):
if (allImages.startswith('TRAIN_SET') and allImages.endswith(".bmp")):
img = cv2.imread(os.path.join(folderDir, allImages))
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_,blackMask = cv2.threshold(gry, 0, 255, cv2.THRESH_BINARY_INV)
x1 = []
y1 = []
def verticle(mask, y, x):
vertiPixel = 0
while(y < mask.shape[0]):
if (y + 1) == mask.shape[0]:
break
else:
if(mask[y + 1][x] == 255):
vertiPixel += 1
y += 1
else:
break
y1.append(vertiPixel)
def horizontal(mask, y, x):
horiPixel = 0
while(x < mask.shape[1]):
if (x + 1) == mask.shape[1]:
break
else:
if(mask[y][x + 1] == 255):
horiPixel += 1
x += 1
else:
break
x1.append(horiPixel)
def mask(mask):
for y in range (mask.shape[0]):
for x in range (mask.shape[1]):
if(mask[y][x] == 255):
verticle(mask, y, x)
horizontal(mask, y, x)
equation(y,x)
def equation(y,x):
a = np.average(y) * (9.9 / 305)
c = np.average(x) * (9.9 / 305)
final = (a + c) / 2
total.append(final)
if __name__ == "__main__":
pool = Pool(8)
print(pool.map(mask, [blackMask] * 3))
pool.close()

Steganography decode is not giving me the right input key how do i fix it?

im not sure if the problem lies in the encode section or the decode i tried to fix it both ways nothing worked!
# Python program implementing Image Steganography
# PIL module is used to extract
# pixels of image and modify it
from PIL import Image
# Convert encoding data into 8-bit binary
# form using ASCII value of characters
def genData(data):
# list of binary codes
# of given data
newd = []
for i in data:
newd.append(format(ord(i), '08b'))
return newd
# Pixels are modified according to the
# 8-bit binary data and finally returned
def modPix(pix, data):
datalist = genData(data)
lendata = len(datalist)
imdata = iter(pix)
for i in range(lendata):
# Extracting 3 pixels at a time
pix = [value for value in imdata.__next__()[:3] +
imdata.__next__()[:3] +
imdata.__next__()[:3]]
# Pixel value should be made
# odd for 1 and even for 0
for j in range(0, 8):
if (datalist[i][j] == '0' and pix[j]% 2 != 0):
pix[j] -= 1
elif (datalist[i][j] == '1' and pix[j] % 2 == 0):
if(pix[j] != 0):
pix[j] -= 1
else:
pix[j] += 1
# pix[j] -= 1
# Eighth pixel of every set tells
# whether to stop ot read further.
# 0 means keep reading; 1 means thec
# message is over.
if (i == lendata - 1):
if (pix[-1] % 2 == 0):
if(pix[-1] != 0):
pix[-1] -= 1
else:
pix[-1] += 1
else:
if (pix[-1] % 2 != 0):
pix[-1] -= 1
pix = tuple(pix)
yield pix[0:3]
yield pix[3:6]
yield pix[6:9]
def encode_enc(newimg, data):
w = newimg.size[0]
(x, y) = (0, 0)
for pixel in modPix(newimg.getdata(), data):
# Putting modified pixels in the new image
newimg.putpixel((x, y), pixel)
if (x == w - 1):
x = 0
y += 1
else:
x += 1
not sure if the problem lies here but i doubt it
# Encode data into image
def encode():
img = input("Enter image name(with extension) : ")
image = Image.open(img, 'r')
data = input("Enter data to be encoded : ")
if (len(data) == 0):
raise ValueError('Data is empty')
newimg = image.copy()
encode_enc(newimg, data)
new_img_name = input("Enter the name of new image(with extension) : ")
newimg.save(new_img_name, str(new_img_name.split(".")[1].upper()))
here is where i think the problem is each time i try to decode the output is "y" i tried to fix it but couldnt find a better solution
# Decode the data in the image
def decode():
img = input("Enter image name(with extension) : ")
image = Image.open(img, 'r')
data = ''
imgdata = iter(image.getdata())
while (True):
pixels = [value for value in imgdata.__next__()[:3] +
imgdata.__next__()[:3] +
imgdata.__next__()[:3]]
# string of binary data
binstr = ''
for i in pixels[:8]:
if (i % 2 == 0):
binstr += '0'
else:
binstr += '1'
data += chr(int(binstr, 2))
if (pixels[-1] % 2 != 0):
return data
the main function works as it should i dont think i made a mistake here
# Main Function
def main():
a = int(input(":: Welcome to Steganography ::\n"
"1. Encode\n2. Decode\n"))
if (a == 1):
encode()
elif (a == 2):
print("Decoded Word : " + decode())
else:
raise Exception("Enter correct input")
# Driver Code
if __name__ == '__main__' :
# Calling main function
main()

IndexError: list index out of range error while enter value like 1 2 3 in Python

I am generating a graph/drawing using pyhton.
When I am entering value from backward like 6 5 4 3 it's working fine but When I am giving input like 1 2 3 it's throwing list index out of range error.
I am new to python. Please help me to fix this.
**EDIT : ** it's only accepting when first value is greater than second value for example it's working with 7 6 but not with 6 7.
here is my python code:
HUMAN_HEIGHT = 3
HUMAN_WIDTH = 3
HUMAN_LEG_OFFSET = 1
def print_2d_array(arr):
"""Print the 2D Array"""
print(f"Height = {len(arr)}, Width = {len(arr[0])}")
for row in arr:
for item in row:
print(f"{item}", end="")
print()
def increasing_slope(index):
"""Returns if the slope is increasing which is the even number"""
return index % 2 == 0
def get_indicator(index):
"""Returns the indicator for increasing or decreasing slope"""
return "/" if increasing_slope(index) else "\\"
def add_human_at(new_arr, human_location, height):
"""Adds Human to the Array"""
human_x = human_location[0]
human_y = human_location[1]
new_arr[height - human_y - 1][human_x - 1] = " "
new_arr[height - human_y - 1][human_x] = "○"
new_arr[height - human_y - 1][human_x + 1] = " "
new_arr[height - human_y][human_x - 1] = "/"
new_arr[height - human_y][human_x] = "|"
new_arr[height - human_y][human_x + 1] = "\\"
new_arr[height - human_y + 1][human_x - 1] = "<"
new_arr[height - human_y + 1][human_x] = " "
new_arr[height - human_y + 1][human_x + 1] = ">"
def create_line(y0, x0, y1, x1, index):
"""Generator that Returns the diagonal line from x,y to x1,y1"""
yield y0, x0
while y0 != y1 and x0 != x1:
y0 = y0 + (-1 if increasing_slope(index) else 1)
x0 += 1
yield y0, x0
def get_2d_mountains_from_1d_sum(arr, height, width, human_location):
new_arr = []
for i in range(height + HUMAN_HEIGHT):
mountain_row = []
for j in range(width + HUMAN_LEG_OFFSET):
mountain_row.append(" ")
new_arr.append(mountain_row)
ground = height + HUMAN_HEIGHT
prev_x, prev_y = 0, 0
for index, [x, y] in enumerate(arr):
indicator = get_indicator(index)
if prev_x >= human_location[0]:
start_x, start_y = ground - prev_y - 1, prev_x + HUMAN_LEG_OFFSET
end_x, end_y = ground - y - 1, x - 1 + HUMAN_LEG_OFFSET
else:
start_x, start_y = ground - prev_y - 1, prev_x
end_x, end_y = ground - y - 1, x - 1
for (point_y, point_x) in create_line(start_x, start_y, end_x, end_y, index):
new_arr[point_y][point_x] = indicator
prev_y = y
prev_x = x
add_human_at(new_arr, human_location, height)
print_2d_array(new_arr)
def generate_mountains(nums):
sum_nums = []
sum_at_position = 0
previous_sum = 0
total_width = 0
max_height = 0
human_location = []
for index, item in enumerate(nums):
# + or - numbers to get prefix list
if index % 2 == 0:
sum_at_position += (item - 1)
else:
sum_at_position -= (item - 1)
total_width += abs(sum_at_position - previous_sum) + 1
if sum_at_position > max_height:
max_height = sum_at_position
human_location = [total_width, max_height]
previous_sum = sum_at_position
sum_nums.append([total_width, sum_at_position])
get_2d_mountains_from_1d_sum(sum_nums, max_height + 1, total_width, human_location)
def print_mountains_human_from_input(nums):
generate_mountains(nums)
print("Enter the inputs")
a = [int(x) for x in input().split()]
print_mountains_human_from_input(a)
I added the screenshot of error..
thanks in advance.
You can add a sorting to your function to avoid a wrong input error but it will not fix the actual error:
def print_mountains_human_from_input(nums):
nums.sort(reverse=True)
generate_mountains(nums)

Extracting the detected objects from image by PILLOW library

the code below is to detect the objects in images. The code can detect the objects, count the number of detected objects, drawing rectangles to label the objects. Is there any way to extract and save each detected objects? For example; if there are 20 objects detected in an image, I would like to extract and save these 20 objects seperately. I would be appreciated for any help..
from PIL import Image
class TheOutliner(object):
''' takes a dict of xy points and
draws a rectangle around them '''
def __init__(self):
self.outlineColor = 255, 0, 0
self.pic = None
self.picn = None
self.minX = 0
self.minY = 0
self.maxX = 0
self.maxY = 0
def doEverything(self, imgPath, dictPoints, theoutfile):
self.loadImage(imgPath)
self.loadBrightPoints(dictPoints)
self.drawBox()
self.saveImg(theoutfile)
def loadImage(self, imgPath):
self.pic = Image.open(imgPath)
self.picn = self.pic.load()
def loadBrightPoints(self, dictPoints):
'''iterate through all points and
gather max/min x/y '''
# an x from the pool (the max/min
# must be from dictPoints)
self.minX = dictPoints.keys()[0][0]
self.maxX = self.minX
self.minY = dictPoints.keys()[0][1]
self.maxY = self.minY
for point in dictPoints.keys():
if point[0] < self.minX:
self.minX = point[0]
elif point[0] > self.maxX:
self.maxX = point[0]
if point[1]< self.minY:
self.minY = point[1]
elif point[1] > self.maxY:
self.maxY = point[1]
def drawBox(self):
# drop box around bright points
for x in xrange(self.minX, self.maxX):
# top bar
self.picn[x, self.minY] = self.outlineColor
# bottom bar
self.picn[x, self.maxY] = self.outlineColor
for y in xrange(self.minY, self.maxY):
# left bar
self.picn[self.minX, y] = self.outlineColor
# right bar
self.picn[self.maxX, y] = self.outlineColor
def saveImg(self, theoutfile):
self.pic.save(theoutfile, "JPEG")
class ObjectDetector(object):
''' returns a list of dicts representing
all the objects in the image '''
def __init__(self):
self.detail = 4
self.objects = []
self.size = 1000
self.no = 255
self.close = 100
self.pic = None
self.picn = None
self.brightDict = {}
def loadImage(self, imgPath):
self.pic = Image.open(imgPath)
self.picn = self.pic.load()
self.picSize = self.pic.size
self.detail = (self.picSize[0] + self.picSize[1])/2000
self.size = (self.picSize[0] + self.picSize[1])/8
# each must be at least 1 -- and the larger
# the self.detail is the faster the analyzation will be
self.detail += 1
self.size += 1
def getSurroundingPoints(self, xy):
''' returns list of adjoining point '''
x = xy[0]
y = xy[1]
plist = (
(x-self.detail, y-self.detail), (x, y-self.detail),
(x+self.detail, y-self.detail),
(x-self.detail, y),(x+self.detail, y),
(x-self.detail, y+self.detail),(x, y+self.detail),
(x+self.detail,y+self.detail)
)
return (plist)
def getRGBFor(self, x, y):
try:
return self.picn[x,y]
except IndexError as e:
return 255,255,255
def readyToBeEvaluated(self, xy):
try:
r,g,b = self.picn[xy[0],xy[1]]
if r==255 and g==255 and b==255:
return False
except:
return False
return True
def markEvaluated(self, xy):
try:
self.picn[xy[0],xy[1]] = self.no, self.no, self.no
except:
pass
def collectAllObjectPoints(self):
for x in xrange(self.pic.size[0]):
if x % self.detail == 0:
for y in xrange(self.pic.size[1]):
if y % self.detail == 0:
r,g,b = self.picn[x,y]
if r == self.no and \
g == self.no and \
b == self.no:
# then no more
pass
else:
ol = {}
ol[x,y] = "go"
pp = []
pp.append((x,y))
stillLooking = True
while stillLooking:
if len(pp) > 0:
xe, ye = pp.pop()
# look for adjoining points
for p in
self.getSurroundingPoints((xe,ye)
if self.readyToBeEvaluated((p[0],
p[1])):
r2,g2,b2 = self.getRGBFor(p[0],
p[1])
if abs(r-r2) < self.close and \
abs(g-g2) < self.close and \
abs(b-b2) < self.close:
# then its close enough
ol[p[0],p[1]] = "go"
pp.append((p[0],p[1]))
self.markEvaluated((p[0],p[1]))
self.markEvaluated((xe,ye))
else:
# done expanding that point
stillLooking = False
if len(ol) > self.size:
self.objects.append(ol)
if __name__ == "__main__":
print "Start Process";
# assumes that the .jpg files are in
# working directory
theFile = "new2"
theOutFile = "new2.output"
import os
os.listdir('.')
for f in os.listdir('.'):
if f.find(".jpg") > 0:
theFile = f
print "working on " + theFile + "..."
theOutFile = theFile + ".out.jpg"
bbb = ObjectDetector()
bbb.loadImage(theFile)
print " analyzing.."
print " file dimensions: " + str(bbb.picSize)
print " this files object weight: " + str(bbb.size)
print " this files analyzation detail: " +
str(bbb.detail)
bbb.collectAllObjectPoints()
print " objects detected: " +str(len(bbb.objects))
drawer = TheOutliner()
print " loading and drawing rectangles.."
drawer.loadImage(theFile)
for o in bbb.objects:
drawer.loadBrightPoints(o)
drawer.drawBox()
print "saving image..."
drawer.saveImg(theOutFile)
print "Process complete"
You can use crop() method :
add new method after drawBox():
def saveBox(self,filename):
# Create Box
box = (self.minX, self.minY, self.maxX, self.maxY)
# Crop Image
self.pic.crop(box).save(filename)
change the main code :
drawer.loadImage(theFile)
idBox=0
for o in bbb.objects:
drawer.loadBrightPoints(o)
drawer.drawBox()
idBox=idBox+1
drawer.saveBox("box_"+str(idBox)+"_"+theOutFile)
print "saving image..."
drawer.saveImg(theOutFile)

PIL saving only the first image

I'm trying to do some batch image processing, but I'm having trouble saving the images once they are created. Here is all of the code:
import Image
import os
import random
training_images = []
training_path = 'cropped'
background_images = []
background_path = 'background'
training_file = 'train'
def get_image_list(file_path):
return os.listdir(file_path)
def rotate_randomely(im):
number = random.randint(1, 6)
if number == 1:
return im.transpose(Image.FLIP_LEFT_RIGHT)
elif number == 2:
return im.transpose(Image.FLIP_TOP_BOTTOM)
elif number == 3:
return im.transpose(Image.ROTATE_90)
elif number == 4:
return im.transpose(Image.ROTATE_180)
elif number == 5:
return im.transpose(Image.ROTATE_270)
else:
return im
def get_random_point(maxX, maxY):
x = random.randint(0, maxX)
y = random.randint(0, maxY)
return x, y
def insert_image(from_image, onto_image):
from_image = resize_smaller(from_image, onto_image.size)
x, y = get_random_point(onto_image.size[0] - from_image.size[0], onto_image.size[1] - from_image.size[0])
onto_image.paste(from_image, (x, y))
width = from_image.size[0]
height = from_image.size[1]
return x, y, width, height
def resize_smaller(image, maxXY):
if image.size[0] > maxXY[0] or image.size[1] > maxXY[1]:
image = image.resize((image.size[0] / 2, image.size[1] / 2))
if image.size[0] > maxXY[0] or image.size[1] > maxXY[1]:
resize_smaller(image, maxXY)
else:
return image
training_images = get_image_list(training_path)
background_images = get_image_list(background_path)
print('training_images size', len(training_images))
print('background_images size', len(background_images))
for training_image in training_images:
index = 0
for background_image in background_images:
name = background_image
training_image = Image.open(training_path + '/' + training_image)
background_image = Image.open(background_path + '/' + background_image)
training_image = rotate_randomely(training_image)
x, y, width, height = insert_image(training_image, background_image)
background_image.save('images/' + str(index) + name)
index = index + 1
The output:
('training_images size', 7)
('background_images size', 1). So it's finding the images correctly, but when I look at the results there is only one image saved, and it only has a 0 pre-pended to the image name. Yet I know it went through each image so there should be seven of them.
I've been looking at this for a while, and I just don't see where I went wrong. Is there something weird about pil's save method that I'm not aware of?
put the index = 0 outside the upper for loop otherwise it will become 0 every iteration and save over the top of old files.

Categories