Python-3, my program doesn't show a negative image - python

So I need to follow the function in my textbook, to make an image negative and show the negative image. I've tried changing a few things in to replicate the previous function see to if that would change anything like typing in what image I want to have a negative of. It compiles and runs fine showing no errors it just doesn't show me a negative of my image, so I don't know whats the issue.
from cImage import *
def negativePixel(oldPixel):
newRed = 255 - oldPixel.getRed()
newGreen = 255 - oldPixel.getGreen()
newBlue = 255 - oldPixel.getBlue()
newPixel = Pixel(newRed, newGreen, newBlue)
return newPixel`
def MakeNegative(imageFile):
oldImage = FileImage(imageFile)
width = oldImage.getWidth()
height = oldImage.getHeight()
myImageWindow = ImageWin("Negative Image", width * 2, height)
oldImage.draw(myImageWindow)
newIn = EmptyImage(width, height)
for row in range(height):
for col in range(width):
oldPixel = oldImage.getPixel(col, row)
newPixel = negativePixel(oldPixel)
newIn.setPixel(col, row, newPixel)
newIn.setPosition(width + 1, 0)
newIn.draw(myImageWindow)
myImageWindow.exitOnClick()

Your code wasn't compiling or running for me; I fixed a few things - indentation, import image (not cImage), not invoking MakeNegative(), parameters out of order, etc. This works for me. I'm on Ubuntu 18.04, Python 3.6.9, cImage-2.0.2, Pillow-7.2.0.
from image import *
def negativePixel(oldPixel):
newRed = 255 - oldPixel.getRed()
newGreen = 255 - oldPixel.getGreen()
newBlue = 255 - oldPixel.getBlue()
newPixel = Pixel(newRed, newGreen, newBlue)
return newPixel
def MakeNegative(imageFile):
oldImage = FileImage(imageFile)
width = oldImage.getWidth()
height = oldImage.getHeight()
myImageWindow = ImageWin(width * 2, height, "Negative Image")
oldImage.draw(myImageWindow)
newIn = EmptyImage(width, height)
for row in range(height):
for col in range(width):
oldPixel = oldImage.getPixel(col, row)
newPixel = negativePixel(oldPixel)
newIn.setPixel(col, row, newPixel)
newIn.setPosition(width + 1, 0)
newIn.draw(myImageWindow)
myImageWindow.exitOnClick()
MakeNegative('Lenna_test_image.png')

Related

How to better crop and paste an image in PIL

I am trying to crop an avatar and place it in a given location in another image using python pil.
Here is the output of what I have so far:
And here is the code:
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import textwrap
text = "Creating Twitter Cards dynamically with Python"
background_image = "data/obi-pvc.png" # this is the background
avatar = Image.open("data/avatar.png")
font = "data/fonts/AllertaStencil-Regular.ttf"
background = Image.open(background_image)
background_width, background_height = background.size
avatar.convert('RGBA')
## DO NOT change below this line!!
save_name = f"{text.lower().replace(' ', '_')}.png"
#textwrapped = textwrap.wrap(text, width=text_wrap_width)
# crop avatar
width, height = avatar.size
x = (width - height)//2
avatar_cropped = avatar.crop((x, 0, x+height, height))
width_cr, height_cr = avatar_cropped.size
# create grayscale image with white circle (255) on black background (0)
mask = Image.new('L', avatar_cropped.size)
mask_draw = ImageDraw.Draw(mask)
width, height = avatar_cropped.size
mask_draw.ellipse((0, 0, width, height), fill=255)
# add mask as alpha channel
avatar_cropped.putalpha(mask)
draw = ImageDraw.Draw(background)
font = ImageFont.truetype(font, font_size)
draw.text((offset,margin), '\n'.join(textwrapped), font=font, fill=color)
x, y = avatar_cropped.size
margin = 40
# left top
position_tl = (0 + margin, 0 + margin)
position_tr = (x - margin - width_cr, 0 + margin)
position_bl = (0 + margin, y - margin - height_cr)
position_br = (x - margin - width_cr, y - margin - height_cr)
background.paste(avatar_cropped, position)
background.save(f"data/output/{save_name}")
display(background)
The avatar should fit within the circle. I can't seem to really figure out how to apply the positioning. Thanks
Here is the avatar:

Error while loading Yolov5 custom model using OpenCV Python

I was trying to predict defects on a metal plate using yolov5 pre-trained weights.it was throwing this error:
**
File "C:\Users\acer.spyder-py3\metallic surface defect detection\untitled3.py", line 59, in post_process
if confidence >= CONFIDENCE_THRESHOLD:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
**
import cv2
import numpy as np
# Constants.
INPUT_WIDTH = 640
INPUT_HEIGHT = 640
SCORE_THRESHOLD = 0.5
NMS_THRESHOLD = 0.45
CONFIDENCE_THRESHOLD = 0.45
# Text parameters.
FONT_FACE = cv2.FONT_HERSHEY_SIMPLEX
FONT_SCALE = 0.7
THICKNESS = 1
# Colors.
BLACK = (0,0,0)
BLUE = (255,178,50)
YELLOW = (0,255,255)
def draw_label(im, label, x, y):
"""Draw text onto image at location."""
# Get text size.
text_size = cv2.getTextSize(label, FONT_FACE, FONT_SCALE, THICKNESS)
dim, baseline = text_size[0], text_size[1]
# Use text size to create a BLACK rectangle.
cv2.rectangle(im, (x,y), (x + dim[0], y + dim[1] + baseline), (0,0,0), cv2.FILLED);
# Display text inside the rectangle.
cv2.putText(im, label, (x, y + dim[1]), FONT_FACE, FONT_SCALE, YELLOW, THICKNESS, cv2.LINE_AA)
def pre_process(input_image, net):
# Create a 4D blob from a frame.
blob = cv2.dnn.blobFromImage(input_image, 1/255, (INPUT_WIDTH, INPUT_HEIGHT), [0,0,0], 1, crop=False)
# Sets the input to the network.
net.setInput(blob)
# Run the forward pass to get output of the output layers.
outputs = net.forward(net.getUnconnectedOutLayersNames())
return outputs
def post_process(input_image, outputs):
# Lists to hold respective values while unwrapping.
class_ids = []
confidences = []
boxes = []
# Rows.
rows = outputs[0].shape[1]
image_height, image_width = input_image.shape[:2]
# Resizing factor.
x_factor = image_width / INPUT_WIDTH
y_factor = image_height / INPUT_HEIGHT
# Iterate through detections.
for r in range(rows):
row = outputs[0][0][r]
confidence = row[4]
# Discard bad detections and continue.
if confidence >= CONFIDENCE_THRESHOLD:
classes_scores = row[5:]
# Get the index of max class score.
class_id = np.argmax(classes_scores)
# Continue if the class score is above threshold.
if (classes_scores[class_id] > SCORE_THRESHOLD):
confidences.append(confidence)
class_ids.append(class_id)
cx, cy, w, h = row[0], row[1], row[2], row[3]
left = int((cx - w/2) * x_factor)
top = int((cy - h/2) * y_factor)
width = int(w * x_factor)
height = int(h * y_factor)
box = np.array([left, top, width, height])
boxes.append(box)
# Perform non maximum suppression to eliminate redundant, overlapping boxes with lower confidences.
indices = cv2.dnn.NMSBoxes(boxes, confidences, CONFIDENCE_THRESHOLD, NMS_THRESHOLD)
for i in indices:
box = boxes[i]
left = box[0]
top = box[1]
width = box[2]
height = box[3]
# Draw bounding box.
cv2.rectangle(input_image, (left, top), (left + width, top + height), BLUE, 3*THICKNESS)
# Class label.
label = "{}:{:.2f}".format(classes[class_ids[i]], confidences[i])
# Draw label.
draw_label(input_image, label, left, top)
return input_image
if __name__ == '__main__':
# Load class names.
classesFile = "defects.names"
classes = None
with open(classesFile, 'rt') as f:
classes = f.read().rstrip('\n').split('\n')
# Load image.
frame = cv2.imread('img_02_3436787300_00007_jpg.rf.e9923d3a70d1aeb92e45896b9c12cfa3.jpg')
# Give the weight files to the model and load the network using them.
modelWeights = "models_train/best.onnx"
net = cv2.dnn.readNet(modelWeights)
# Process image.
detections = pre_process(frame, net)
img = post_process(frame.copy(), detections)
"""
Put efficiency information. The function getPerfProfile returns the overall time for inference(t)
and the timings for each of the layers(in layersTimes).
"""
t, _ = net.getPerfProfile()
label = 'Inference time: %.2f ms' % (t * 1000.0 / cv2.getTickFrequency())
print(label)
cv2.putText(img, label, (20, 40), FONT_FACE, FONT_SCALE, (0, 0, 255), THICKNESS, cv2.LINE_AA)
cv2.imshow('Output', img)
cv2.waitKey(0)
I have little bit idea of deploying models into commercial use. If you find any other errors also please inform me . thanks in advance
A simple search led me to this SO post, highlighting a common issue recently.
Following this blog got me close but I faced the issue above.
net.getUnconnectedOutLayers() returns an array of index values. The output layers are obtained from net.getLayerNames() based on these index values.
In the following case net.getUnconnectedOutLayers() returns:
array([200, 227, 254])
We get the output layers from output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers() which returns:
['yolo_82', 'yolo_94', 'yolo_106']
Code:
The following is the complete working code for OpenCV version 4.5.5 (CPU):
image = cv2.imread(os.path.join(path, 'horse.jpg'))
Width = image.shape[1]
Height = image.shape[0]
scale = 0.00392
classes = None
with open(os.path.join(path, 'coco.names'), 'r') as f:
classes = [line.strip() for line in f.readlines()]
COLORS = np.random.uniform(0, 255, size=(len(classes), 3))
net = cv2.dnn.readNet(os.path.join(path, 'yolov3.weights'), os.path.join(path, 'yolov3.cfg'))
blob = cv2.dnn.blobFromImage(image, scale, (416,416), (0,0,0), True, crop=False)
net.setInput(blob)
def get_output_layers(net):
layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers()]
return output_layers
def draw_bounding_box(img, class_id, confidence, x, y, x_plus_w, y_plus_h):
label = str(classes[class_id])
color = COLORS[class_id]
img = cv2.rectangle(img, (x,y), (x_plus_w,y_plus_h), color, 2)
img = cv2.putText(img, label, (x-10,y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# run inference through the network
# and gather predictions from output layers
outs = net.forward(get_output_layers(net))
# initialization
class_ids = []
confidences = []
boxes = []
conf_threshold = 0.5
nms_threshold = 0.4
image2 = image.copy()
for out in outs:
for detection in out:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.5:
center_x = int(detection[0] * Width)
center_y = int(detection[1] * Height)
w = int(detection[2] * Width)
h = int(detection[3] * Height)
x = center_x - w / 2
y = center_y - h / 2
class_ids.append(class_id)
confidences.append(float(confidence))
boxes.append([x, y, w, h])
# apply non-max suppression
indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold)
for i in indices:
i = i # i[0]
box = boxes[i]
x = box[0]
y = box[1]
w = box[2]
h = box[3]
draw_bounding_box(image2, class_ids[i], confidences[i], round(x), round(y), round(x+w), round(y+h))
Result:
Sample output:
The problem may be related to incompatible version of your installed modules.
Download .pt model.
wget https://github.com/ultralytics/YOLOv5/releases/download/v6.1/YOLOv5s.pt
And export to ONNX using your machine:
git clone https://github.com/ultralytics/YOLOv5
cd YOLOv5
pip install -r requirements.txt
pip install onnx
python3 export.py --weights models/YOLOv5s.pt --include onnx
Use the new converted .onnx file can solve the problem.

How to get loop to start on a mouse click in python

I am struggling to find a way to get my program to change the image to grayscale after the user clicks on the original image. The curly brackets are where I believe my problem is.
import image
img = image.Image("nature.jpg")
win = image.ImageWin(img.getWidth(), img.getHeight())
img.draw(win)
img.setDelay(1,15)
if {}:
for row in range(img.getHeight()):
for col in range(img.getWidth()):
p = img.getPixel(col, row)
aver = (p.getRed() + p.getGreen() + p.getBlue())/3
newred = aver
newgreen = aver
newblue = aver
newpixel = image.Pixel(newred, newgreen, newblue)
img.setPixel(col, row, newpixel)
img.draw(win)

Remove all empty space from image

I need to remove all white-spaces from image but I don't know how to do it..
I am using trim functionality to trim white spaces from border but still white-spaces are present in middle of image I am attaching my original image from which I want to remove white-spaces
my code
from PIL import Image, ImageChops
import numpy
def trim(im):
bg = Image.new(im.mode, im.size, im.getpixel((0, 0)))
diff = ImageChops.difference(im, bg)
diff = ImageChops.add(diff, diff, 2.0, -100)
box = diff.getbbox()
if box:
im.crop(box).save("trim_pil.png")
im = Image.open("/home/einfochips/Documents/imagecomparsion/kroger_image_comparison/SnapshotImages/screenshot_Hide.png")
im = trim(im)
but this code only remove space from borders, I need to remove spaces from middle also. Please help if possible, it would be very good if I got all five images in different PNG file.
You could go the long way with a for loop
from PIL import Image, ImageChops
def getbox(im, color):
bg = Image.new(im.mode, im.size, color)
diff = ImageChops.difference(im, bg)
diff = ImageChops.add(diff, diff, 2.0, -100)
return diff.getbbox()
def split(im):
retur = []
emptyColor = im.getpixel((0, 0))
box = getbox(im, emptyColor)
width, height = im.size
pixels = im.getdata()
sub_start = 0
sub_width = 0
offset = box[1] * width
for x in range(width):
if pixels[x + offset] == emptyColor:
if sub_width > 0:
retur.append((sub_start, box[1], sub_width, box[3]))
sub_width = 0
sub_start = x + 1
else:
sub_width = x + 1
if sub_width > 0:
retur.append((sub_start, box[1], sub_width, box[3]))
return retur
This makes it easy to retrieve the crop boxes in the image like this:
im = Image.open("/home/einfochips/Documents/imagecomparsion/kroger_image_comparison/SnapshotImages/screenshot_Hide.png")
for idx, box in enumerate(split(im)):
im.crop(box).save("trim_{0}.png".format(idx))
If you already know the size of the images toy want to extract you could go with
def split(im, box):
retur = []
pixels = im.getdata()
emptyColor = pixels[0]
width, height = im.size;
y = 0;
while y < height - box[3]:
x = 0
y_step = 1
while x < width - box[2]:
x_step = 1
if pixels[y*width + x] != emptyColor:
retur.append((x, y, box[2] + x, box[3] + y))
y_step = box[3] + 1
x_step = box[2] + 1
x += x_step
y += y_step
return retur
Adding another parameter to the call
for idx, box in enumerate(split(im, (0, 0, 365, 150))):
im.crop(box).save("trim_{0}.png".format(idx))

image tiling in loops using Python OpenCV

Python noob needs some help guys! Can someone show me how to rewrite my code using loops? Tried some different syntaxes but did not seem to work!
img = cv2.imread("C://Users//user//Desktop//research//images//Underwater_Caustics//set1//set1_color_0001.png")
tile11=img[1:640, 1:360]
cv2.imwrite('tile11_underwater_caustic_set1_0001.png', tile11)
tile12=img[641:1280, 1:360]
cv2.imwrite('tile12_underwater_caustic_set1_0001.png', tile12)
tile13=img[1281:1920, 1:360]
cv2.imwrite('tile13_underwater_caustic_set1_0001.png', tile13)
tile21=img[1:640, 361:720]
cv2.imwrite('tile21_underwater_caustic_set1_0001.png', tile21)
tile22=img[641:1280, 361:720]
cv2.imwrite('tile22_underwater_caustic_set1_0001.png', tile22)
tile23=img[1281:1920, 361:720]
cv2.imwrite('tile23_underwater_caustic_set1_0001.png', tile23)
tile31=img[1:640, 721:1080]
cv2.imwrite('tile31_underwater_caustic_set1_0001.png', tile31)
tile32=img[641:1280, 721:1080]
cv2.imwrite('tile32_underwater_caustic_set1_0001.png', tile32)
tile33=img[1281:1920, 721:1080]
cv2.imwrite('tile33_underwater_caustic_set1_0001.png', tile33)
As you can see, the image will be cut into 9 equal-size pieces, how to write it using loops?
This won't produce the same result like your code, but will give you some ideas:
img = cv2.imread('sample.jpg')
numrows, numcols = 4, 4
height = int(img.shape[0] / numrows)
width = int(img.shape[1] / numcols)
for row in range(numrows):
for col in range(numcols):
y0 = row * height
y1 = y0 + height
x0 = col * width
x1 = x0 + width
cv2.imwrite('tile_%d%d.jpg' % (row, col), img[y0:y1, x0:x1])
I needed image tiling where last parts or edge tiles are required to be full tile images.
Here is the code I use:
import cv2
import math
import os
Path = "FullImage.tif";
filename, file_extension = os.path.splitext(Path)
image = cv2.imread(Path, 0)
tileSizeX = 256;
tileSizeY = 256;
numTilesX = math.ceil(image.shape[1]/tileSizeX)
numTilesY = math.ceil(image.shape[0]/tileSizeY)
makeLastPartFull = True; # in case you need even siez
for nTileX in range(numTilesX):
for nTileY in range(numTilesY):
startX = nTileX*tileSizeX
endX = startX + tileSizeX
startY = nTileY*tileSizeY
endY = startY + tileSizeY;
if(endY > image.shape[0]):
endY = image.shape[0]
if(endX > image.shape[1]):
endX = image.shape[1]
if( makeLastPartFull == True and (nTileX == numTilesX-1 or nTileY == numTilesY-1) ):
startX = endX - tileSizeX
startY = endY - tileSizeY
currentTile = image[startY:endY, startX:endX]
cv2.imwrite(filename + '_%d_%d' % (nTileY, nTileX) + file_extension, currentTile)
This is for massive image reconstruction using part of flowfree his code. By using a folder of sliced images in the same area the script is, you can rebuild the image. I hope this helps.
import cv2
import glob
import os
dir = "."
pathname = os.path.join(dir, "*" + ".png")
images = [cv2.imread(img) for img in glob.glob(pathname)]
img = images[0]
numrows, numcols = 1,1
height = int(img.shape[0] / numrows)
width = int(img.shape[1] / numcols)
for row in range(numrows):
for col in range(numcols):
y0 = row * height
y1 = y0 + height
x0 = col * width
x1 = x0 + width
cv2.imwrite('merged_img_%d%d.jpg' % (row, col), img[y0:y1, x0:x1])

Categories