in my case, there are 2 ways of getting image to resize/crop.
upload normal image file
giving base64 string data of image
in 1. case, resize and crop is working well:
f = Image.open(uploaded_image)
new_width, new_height = 1200, 630
wpercent = (new_width / float(f.size[0]))
hsize = int((float(f.size[1]) * float(wpercent)))
if f.mode != "RGB":
f = f.convert('RGB')
og_img = None
if f.size[0] < new_width:
#upscale
og_img = f.resize((new_width, hsize), Image.BICUBIC)
elif f.size[0] >= new_width:
#downscale
og_img = f.resize((new_width, hsize), Image.ANTIALIAS)
og_img = og_img.crop((0, 0, 1200, 630))
resized/cropped image:
in 2. case, the code is the same as above with slight change in:
base64_image = str(request.POST.get('base64_image')).split(',')[1]
imgfile = open('/'.join([settings.MEDIA_ROOT, 'test.png' ]), 'w+b')
imgfile.write(decodestring(base64_image))
imgfile.seek(0)
f = Image.open(imgfile)
#.. as above
but the resized/cropped image:
why is it in 2.case bad in quality and size? (black bottom part..) what am I doing wrong? am I reading the base64 string in wrong way?
I found a website which has many interesting things in it.It has 2(there are many) tools which maybe can help you.The 1th tool converts image to base64 and the 2th tool minifies the size of image (up to 70% save).
http://www.w3docs.com/tools/minimage/
http://www.w3docs.com/tools/image-base64
Related
I am trying to develop a script which will detect pixelation from LiveTV from an external camera. To test my script I have been using a short snippet of LiveTV which has two instances of pixelation.
See Google Drive below for video:
https://drive.google.com/file/d/1f339HJSWKhyPr1y5sf9tWW4vcXgBOVbz/view?usp=sharing
Currently I am able to filter out most of the noise in the video, and detect the pixelation. However, I am also detecting the white text (given the intensity of the text it gets picked up by the kernel I am applying).
See the code below:
import cv2
import numpy as np
cap = cv2.VideoCapture("./hgtv_short.ts")
while True:
success, image = cap.read()
gray = cv2.cvtColor(src=image, code=cv2.COLOR_BGR2GRAY)
sharpen_kernel = np.array([[.4, .4], [-2.25, -2.25], [.4, .4]])
sharpen = cv2.filter2D(src=gray, ddepth=-1, kernel=sharpen_kernel)
sharpe = sharpen + 128
canny = cv2.Canny(image=sharpe, threshold1=245, threshold2=255, edges=1, apertureSize=3, L2gradient=True)
white = np.where(canny != [0])
coordinates = zip(white[1], white[0])
for p in coordinates:
cv2.circle(canny, p, 30, (200, 0, 0), 2)
cv2.imshow('image', image)
cv2.imshow('edges', canny)
cv2.waitKey(1)
What I would like to do is apply a threshold and findContours to the given coordinates to see if text is in the region. Then I can discern between actual pixelation and text.
NOTE:
If anyone has any other ideas on finding pixelation I am open to suggestions.
UPDATE
Here is a screenshot from the video showing the type of pixelation I am looking for in this video (macro-blocking) to be specific.
Image
Edges
From the above Images you can see that I am detecting the macro-blocking, but also the white text. I would like to be able to discern between text and actual macro-blocking.
SECOND UPDATE
After more trial and error, I found that it will be best to use some sort of reference model to help predict when an image is showing macro-blocking, pixelation, artifacts, etc...
I have decided to use the hog(Histogram of Oriented Gradients) descriptor to create my feature vector. I have created to functions, one loops through the GOOD images and the other the BAD images:
def pos_train_set(self):
print("Starting to Gather Positive Photos")
for pos_file in glob.iglob(os.path.join(self.base_path, "Bad_Images", "*.jpg")):
pos_img = cv2.imread(pos_file, 1)
pos_img = cv2.resize(pos_img, self.winSize, interpolation=cv2.CV_32F)
pos_des = self.hog.compute(pos_img)
pos_des = cv2.normalize(pos_des, None)
self.labels.append(1)
self.training_data.append(pos_des)
print("Gathered Positive Photos")
def neg_train_set(self):
print("Starting to Gather Negative Photos")
for neg_file in glob.iglob(os.path.join(self.base_path, "Good_Images", "*.jpg")):
neg_img = cv2.imread(neg_file, 1)
neg_img = cv2.resize(neg_img, self.winSize, interpolation=cv2.CV_32F)
neg_des = self.hog.compute(neg_img)
neg_des = cv2.normalize(neg_des, None)
self.labels.append(0)
self.training_data.append(neg_des)
print("Gathered Negative Photos")
I then train my model using the SVM(Support Vector Machines) classification algorithm.
def train_set(self):
print("Starting to Convert")
td = np.float32(self.training_data)
lab = np.array(self.labels)
print("Converted List")
print("Starting Shuffle")
rand = np.random.RandomState(10)
shuffle = rand.permutation(len(td))
td = td[shuffle]
lab = lab[shuffle]
print("Shuffled List")
print("Starting SVM")
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
# Exponential Chi2 kernel, similar to the RBF kernel: K(xi,xj)=e−γχ2(xi,xj),χ2(xi,xj)=(xi−xj)2/(xi+xj),γ>0.
svm.setKernel(cv2.ml.SVM_CHI2)
svm.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6))
svm.setGamma(5.383)
svm.setC(2.67)
print("Starting Training")
svm.train(td, cv2.ml.ROW_SAMPLE, lab)
print("Saving to .yml")
svm.save(os.path.join(self.base_path, "svm_model.yml"))
I then use that SVM model to try and predict if an image is a 1 (Bad Image) or a 0 (Good Image). With the help of the kernel and edge detection I used in my first attempt:
def predict(self):
svm = cv2.ml.SVM_load("./svm_model.yml")
for file in self.files:
os.mkdir(os.path.join(self.base_path, "1_Frames", os.path.basename(file)))
print(f"Starting predict on {file}")
cap = cv2.VideoCapture(file)
while cap.isOpened():
success, image = cap.read(1)
if success:
img = cv2.resize(image, self.winSize, interpolation=cv2.CV_32F)
test_data = self.hog.compute(img)
test_data = cv2.normalize(test_data, None)
test_data = np.float32(test_data)
test_data = np.transpose(test_data)
if not np.any(test_data):
print("Invalid Dimension")
success, image = cap.read(1)
print(f"New Frame {success}")
else:
response = svm.predict(test_data)[1]
if response == 1:
gray = cv2.cvtColor(src=image, code=cv2.COLOR_BGR2GRAY)
sharpen_kernel = np.array([[.4, .4], [-2.25, -2.25], [.4, .4]])
sharpen = cv2.filter2D(src=gray, ddepth=-1, kernel=sharpen_kernel)
sharpe = sharpen + 128
canny = cv2.Canny(image=sharpe, threshold1=245, threshold2=255, edges=1, apertureSize=3, L2gradient=True)
white = np.where(canny != [0])
if not len(white[0]) == 0:
cv2.imwrite(os.path.join(self.base_path, '1_Frames', os.path.basename(file), f'found_{self.x}.jpg'), image)
success, image = cap.read(1)
self.x += 1
else:
success, image = cap.read(1)
pass
else:
cv2.imwrite(os.path.join(self.base_path, '0_Frames', f'found_{self.y}.jpg'), image)
success, image = cap.read(1)
self.y += 1
else:
break
cap.release()
cv2.destroyAllWindows()
This method seems to work well, but I am still open to any further ideas of suggestions. I posted this new update in hopes it may assist someone else looking for suggestions on how to detect issues in images.
I have a python flask-restful API, I am trying to add the feature to allow users to upload GIFs, the client will upload a base64-encoded GIF to the API for that, so on the API I need to be able to decode base64 to GIF and also be able to do operations on it such as resizing and compression then convert it to bytes
I tried to do with PIL like this:
img_bytes = BytesIO()
# I specified the duration to be 67 because I want the GIF to play at 15 FPS, 1000 / 15 = 66.66
self.image.save(img_bytes, append_images=self.frames[1:], format=self.format, save_all=True,
optimize=False, duration=67, loop=0)
img_bytes.seek(0)
The problem with that implementation is that I find a lot of distortion and black pixels in the GIFs and inconsistent framerate/animation speed, it's overall pretty bad and it makes a 75 KBs GIF be 1.8 MBs, any other solutions?
Try the code below. It works for me.
from PIL import Image
import base64
import os
myimagestring = "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"
myimagedata = base64.b64decode(myimagestring)
myimagefile= open("myimage.gif","wb")
myimagefile.write(myimagedata)
myimagefile.close()
myimageobject = PhotoImage(file="myimage.gif")
And here is a function to resize the image if needed:
from PIL import Image
def get_resized_img(img_path, picture_size):
img = Image.open(img_path)
width, height = picture_size # these are the MAX dimensions
picture_ratio = width / height
img_ratio = img.size[0] / img.size[1]
if picture_ratio >= 1: # the picture is wide
if img_ratio <= picture_ratio: # image is not wide enough
width_new = int(height * img_ratio)
size_new = width_new, height
else: # image is wider than picture
height_new = int(width / img_ratio)
size_new = width, height_new
else: # the picture is tall
if img_ratio >= picture_ratio: # image is not tall enough
height_new = int(width / img_ratio)
size_new = width, height_new
else: # image is taller than picture
width_new = int(height * img_ratio)
size_new = width_new, height
return img.resize(size_new, resample=Image.LANCZOS)
I am trying to generate PDF files from generated image. The generated PDF file has high level of pixelation on zooming in which is creating shadows during printing.
Image of zoomed in qrcode from PDF
Showing gray zone around qrcode modules and pixels (gray) which should be white otherwise. It does not matter if the desired_resolution matches or is lower than the resolution in which the original image was created.
What could be the issue and possible fixes?
qr_size_mm = 8
MM2PX_FACTOR = 94.48 # 2400 dpi
def create_code(prefix, number, postfix=None):
message = prefix + str(number)
message += postfix if postfix is not None else ""
series_qrcode = pyqrcode.create(message, error='H', version=3, mode='binary')
# print(series_qrcode.get_png_size())
binary = BytesIO()
desired_scale = int(qr_size_px / series_qrcode.get_png_size())
series_qrcode.png(binary, scale=desired_scale, module_color=(0, 0, 0),
background=(255, 255, 255), quiet_zone=3)
tmpIm = Image.open(binary).convert('RGB')
qr_dim = tmpIm.getbbox()
# print(qr_dim)
return tmpIm, qr_dim
qr_size_px = int(qr_size_mm * MM2PX_FACTOR)
# create A4 canvas
paper_width_mm = 210
paper_height_mm = 297
start_offset_mm = 10
start_offset_px = start_offset_mm * MM2PX_FACTOR
canvas_width_px = int(paper_width_mm * MM2PX_FACTOR)
canvas_height_px = int(paper_height_mm * MM2PX_FACTOR)
pil_paper_canvas = Image.new('RGB', (canvas_width_px, canvas_height_px), (255, 255, 255))
# desired pixels for 1200 dpi print
required_resolution_px = 94.48 # 47.244 # 23.622
required_resolution = 2400
print("Page dimension {page_width} {page_height} offset {offset}".format(page_width=canvas_width_px, page_height=canvas_height_px, offset=start_offset_px))
start_range = 10000100000000
for n in range(0, 5):
print("Generating ", start_range+n)
qr_image, qr_box = create_code("TLTR", number=start_range+n)
# qr_image.show()
print("qr_box ", qr_box)
qr_x = int(start_offset_px + ((n+1) * qr_box[2]))
qr_y = int(start_offset_px)
print("pasting at ", qr_x, qr_y)
pil_paper_canvas.paste(qr_image, (qr_x, qr_y))
# create a canvas just for current qrcode
one_qr_canvas = Image.new('RGB', (int(10*MM2PX_FACTOR), int(10*MM2PX_FACTOR)), (255, 255, 255))
qrXY = int((10*MM2PX_FACTOR - qr_box[2]) / 2)
one_qr_canvas.paste(qr_image, (qrXY, qrXY))
one_qr_canvas = one_qr_canvas.resize((int(qr_size_mm*required_resolution_px),
int(qr_size_mm*required_resolution_px)))
one_qr_canvas.save(form_full_path("TLTR"+str(start_range+n)+".pdf"), dpi=(required_resolution, required_resolution))
pil_paper_canvas = pil_paper_canvas.resize((int(paper_width_mm*required_resolution_px),
int(paper_height_mm*required_resolution_px)))
# pil_paper_canvas.show()
pil_paper_canvas.save(form_full_path("TLTR_qr_A4.pdf"), dpi=(required_resolution, required_resolution))
I incorporated 3 changes to fix/workaround the issue:
Instead of specifying fixed number for resizing, switched to scale (m*n).
Used lineType=cv2.LINE_AA for anti-aliasing as suggested by #physicalattraction
That still one issue unresolved which was that PIL generated PDF #96dpi which is not good for printing. Was unable to figure the option to use Print-ready PDF (PDF/A or something on those lines). Hence switched to generating PNG to generate high-quality qrcodes.
My output doesn't show anything and I honestly can't find out why
This is the full code, but I think the problem is when I'm passing the argument to aRed, aGreen, aBlue, originalImage = openImage(response.content)
When I run that code in collab python notebook, my image isn't showing up for some reason! Maybe it's the way I'm passing the URL as an argument in the line above?
import numpy
from PIL import Image
import requests
from io import BytesIO
# FUNCTION DEFINTIONS:
# open the image and return 3 matrices, each corresponding to one channel (R, G and B channels)
def openImage(imagePath):
imOrig = Image.open(BytesIO(imagePath))
im = numpy.array(imOrig)
aRed = im[:, :, 0]
aGreen = im[:, :, 1]
aBlue = im[:, :, 2]
return [aRed, aGreen, aBlue, imOrig]
# compress the matrix of a single channel
def compressSingleChannel(channelDataMatrix, singularValuesLimit):
uChannel, sChannel, vhChannel = numpy.linalg.svd(channelDataMatrix)
aChannelCompressed = numpy.zeros((channelDataMatrix.shape[0], channelDataMatrix.shape[1]))
k = singularValuesLimit
leftSide = numpy.matmul(uChannel[:, 0:k], numpy.diag(sChannel)[0:k, 0:k])
aChannelCompressedInner = numpy.matmul(leftSide, vhChannel[0:k, :])
aChannelCompressed = aChannelCompressedInner.astype('uint8')
return aChannelCompressed
# MAIN PROGRAM:
response = requests.get('https://i.imgur.com/BIOFZNo.png')
print ('*** Image Compression using SVD - a demo')
aRed, aGreen, aBlue, originalImage = openImage(response.content)
# image width and height:
imageWidth = 1000
imageHeight = 1000
#number of singular values to use for reconstructing the compressed image
singularValuesLimit = 160
aRedCompressed = compressSingleChannel(aRed, singularValuesLimit)
aGreenCompressed = compressSingleChannel(aGreen, singularValuesLimit)
aBlueCompressed = compressSingleChannel(aBlue, singularValuesLimit)
imr=Image.fromarray(aRedCompressed,mode=None)
img=Image.fromarray(aGreenCompressed,mode=None)
imb=Image.fromarray(aBlueCompressed,mode=None)
newImage = Image.merge("RGB", (imr,img,imb))
originalImage.show()
newImage.show()
There are no errors in compiling the program, it just doesn't show up anything.
Thank you all!
Here is the link to my file: https://colab.research.google.com/drive/12K0nWKRdOpZ3gSfTn0wuP8Y0_UUeUxEE
You don't need to specify .show() in interactive modes. Just remove that part, and it will work fine.
import numpy
from PIL import Image
import requests
from io import BytesIO
# FUNCTION DEFINTIONS:
# open the image and return 3 matrices, each corresponding to one channel (R, G and B channels)
def openImage(imagePath):
imOrig = Image.open(BytesIO(imagePath))
im = numpy.array(imOrig)
aRed = im[:, :, 0]
aGreen = im[:, :, 1]
aBlue = im[:, :, 2]
return [aRed, aGreen, aBlue, imOrig]
# compress the matrix of a single channel
def compressSingleChannel(channelDataMatrix, singularValuesLimit):
uChannel, sChannel, vhChannel = numpy.linalg.svd(channelDataMatrix)
aChannelCompressed = numpy.zeros((channelDataMatrix.shape[0], channelDataMatrix.shape[1]))
k = singularValuesLimit
leftSide = numpy.matmul(uChannel[:, 0:k], numpy.diag(sChannel)[0:k, 0:k])
aChannelCompressedInner = numpy.matmul(leftSide, vhChannel[0:k, :])
aChannelCompressed = aChannelCompressedInner.astype('uint8')
return aChannelCompressed
# MAIN PROGRAM:
response = requests.get('https://i.imgur.com/BIOFZNo.png')
print ('*** Image Compression using SVD - a demo')
aRed, aGreen, aBlue, originalImage = openImage(response.content)
# image width and height:
imageWidth = 1000
imageHeight = 1000
#number of singular values to use for reconstructing the compressed image
singularValuesLimit = 160
aRedCompressed = compressSingleChannel(aRed, singularValuesLimit)
aGreenCompressed = compressSingleChannel(aGreen, singularValuesLimit)
aBlueCompressed = compressSingleChannel(aBlue, singularValuesLimit)
imr=Image.fromarray(aRedCompressed,mode=None)
img=Image.fromarray(aGreenCompressed,mode=None)
imb=Image.fromarray(aBlueCompressed,mode=None)
newImage = Image.merge("RGB", (imr,img,imb))
originalImage
OriginalImage will be displayed. For new image, in next code cell:
newImage
I've written a script in python in combination with pytesseract to extract a word out of an image. There is only a single word TOOLS available in that image and that is what I'm after. Currently my below script is giving me wrong output which is WIS. What Can I do to get the text?
Link to that image
This is my script:
import requests, io, pytesseract
from PIL import Image
response = requests.get('http://facweb.cs.depaul.edu/sgrais/images/Type/Tools.jpg')
img = Image.open(io.BytesIO(response.content))
img = img.resize([100,100], Image.ANTIALIAS)
img = img.convert('L')
img = img.point(lambda x: 0 if x < 170 else 255)
imagetext = pytesseract.image_to_string(img)
print(imagetext)
# img.show()
This is the status of the modified image when I run the above script:
The output I'm having:
WIS
Expected output:
TOOLS
The key is matching image transformation to the tesseract abilities. Your main problem is that the font is not a usual one. All you need is
from PIL import Image, ImageEnhance, ImageFilter
response = requests.get('http://facweb.cs.depaul.edu/sgrais/images/Type/Tools.jpg')
img = Image.open(io.BytesIO(response.content))
# remove texture
enhancer = ImageEnhance.Color(img)
img = enhancer.enhance(0) # decolorize
img = img.point(lambda x: 0 if x < 250 else 255) # set threshold
img = img.resize([300, 100], Image.LANCZOS) # resize to remove noise
img = img.point(lambda x: 0 if x < 250 else 255) # get rid of remains of noise
# adjust font weight
img = img.filter(ImageFilter.MaxFilter(11)) # lighten the font ;)
imagetext = pytesseract.image_to_string(img)
print(imagetext)
And voila,
TOOLS
are recognized.
The key issue with your implementation lies here:
img = img.resize([100,100], Image.ANTIALIAS)
img = img.point(lambda x: 0 if x < 170 else 255)
You could try different sizes and different threshold:
import requests, io, pytesseract
from PIL import Image
from PIL import ImageFilter
response = requests.get('http://facweb.cs.depaul.edu/sgrais/images/Type/Tools.jpg')
img = Image.open(io.BytesIO(response.content))
filters = [
# ('nearest', Image.NEAREST),
('box', Image.BOX),
# ('bilinear', Image.BILINEAR),
# ('hamming', Image.HAMMING),
# ('bicubic', Image.BICUBIC),
('lanczos', Image.LANCZOS),
]
subtle_filters = [
# 'BLUR',
# 'CONTOUR',
'DETAIL',
'EDGE_ENHANCE',
'EDGE_ENHANCE_MORE',
# 'EMBOSS',
'FIND_EDGES',
'SHARPEN',
'SMOOTH',
'SMOOTH_MORE',
]
for name, filt in filters:
for subtle_filter_name in subtle_filters:
for s in range(220, 250, 10):
for threshold in range(250, 253, 1):
img_temp = img.copy()
img_temp.thumbnail([s,s], filt)
img_temp = img_temp.convert('L')
img_temp = img_temp.point(lambda x: 0 if x < threshold else 255)
img_temp = img_temp.filter(getattr(ImageFilter, subtle_filter_name))
imagetext = pytesseract.image_to_string(img_temp)
print(s, threshold, name, subtle_filter_name, imagetext)
with open('thumb%s_%s_%s_%s.jpg' % (s, threshold, name, subtle_filter_name), 'wb') as g:
img_temp.save(g)
and see what works for you.
I would suggest you resize your image while keeping the original ratio. You could also try some alternative to img_temp.convert('L')
Best so far: TWls and T0018
You can try to manipulate the image manually and see if you can find some edit that can provide a better output (for instance http://gimpchat.com/viewtopic.php?f=8&t=1193)
By knowing in advance the font you could probably achieve a better result too.