How to perform ImageMagick gradient call with python wand - python-2.7

Trying to convert this ImageMagick command to Python Wand code but I don't see a means to create a gradient image with Wand.
convert -size 800x800 gradient:"rgba(0,0,0,0.12)-rgba(0,0,0,1)" gradient_overlay.png
convert gradient_overlay.png background.png -compose Overlay -composite -depth 8 background_gradient.png
Does anyone know how I could achieve this with wand?

You will need to allocate an instance of wand, set canvas size, then read the pseudo-image format.
from wand.image import Image
from wand.api import library
with Image() as canvas:
library.MagickSetSize(canvas.wand, 800, 800)
canvas.read(filename="gradient:rgba(0,0,0,0.12)-rgba(0,0,0,1)")
canvas.save(filename="gradient_overlay.png")

ImageMagick Equivalent For Use With Wand
I have not used Wand, but I can show you how to do it by reference to ImageMagick. You can create a new transparent image. Then use the fx operator to modify the alpha channel into a gradient.
The equivalent Wand references are:
Create a new transparent image (the default) - see http://docs.wand-py.org/en/0.4.1/guide/read.html?highlight=new%20image#open-empty-image
Use fx to convert the alpha channel to a gradient - see http://docs.wand-py.org/en/0.4.1/wand/image.html
convert -size 800x800 xc:transparent -channel a -fx "(j*(1-0.12)/(h-1)+0.12)" +channel alpha.png
Here is how I got the fx formula:
You want a 12% gray at the top (0.12) and 100% gray/white at the bottom (1.0). So we take the formula:
c = a*j + b
At j=0 the top, you need 0.12, so
0.12 = a*0 + b --> b = 0.12
At j=(h-1) the bottom, you want 1, so
1 = a*(h-1) + 0.12 --> a = (1-0.12)/(h-1)
So the equation is:
c = j*(1-0.12)/(h-1) + 0.12
h is the height of the image (800).

Here is how I solved it based fmw42 feedback
with Color('black') as blackColor:
with Image(width=800, height=800, background=blackColor) as black:
blackPath = existing[:existing.rfind('/') + 1] + 'black.png'
with Color('white') as whiteColor:
with Image(width=800, height=800, background=whiteColor) as alpha:
fxFilter = "(j*(1-0.12)/(h-1)+0.12)"
with alpha.fx(fxFilter) as filteredImage:
black.composite_channel('default_channels', filteredImage, 'copy_opacity', 0, 0)
black.save(filename=blackPath)

Related

Generating the background of imatest color error chart generated by using color checker?

I am having some trouble finding the background of the following plot made using imatest. Basically what I want to know is that how, or from where, can I find the background of this plot. The imatest website mentions that the colors of the chart are generated at a constant Luminance L* = 90 and by varing a* and b* from -80 to +80. I have been looking for Lab color generator but all software generate colored points. But I want to get a continuous image by varying the a and b values. Any idea?
Using matlab you can simply transform your cielab space into RGB space:
range = -80:0.5:80; % a,b range, change the step to change the size of the output image.
L = 100*ones(size(range,2),size(range,2)); % L intensity
[b,a] = meshgrid(range); % generate a 2D grid
Lab = cat(3,L,a,b); % create the 3D Lab array
I = lab2rgb(rot90(Lab)); % Lab -> RGB
imshow(I) % Display the result
And we obtain:
Just for fun, if anyone wants a Python OpenCV version, I made one like this:
#!/usr/bin/env python3
import cv2
import numpy as np
# Set size of output image
h, w = 500, 500
# Create "L" channel, L=90
L = np.full((h,w), 90.00, np.float32)
# Create "a" channel, -80 to +80
a = np.linspace(-80,80,w,endpoint=True,dtype=np.float32)
a = np.resize(a,(h,w))
# Create "b" channel by rotating "a" channel 90 degrees
b = cv2.rotate(a, cv2.ROTATE_90_COUNTERCLOCKWISE)
# Stack the 3-channels into single image and convert from Lab to BGR
res = np.dstack((L,a,b))
res = cv2.cvtColor(res, cv2.COLOR_LAB2BGR)
# Save result
cv2.imwrite('result.png', (res*65535).astype(np.uint16))

OpenCV - Extract letters from string using python

I have an image
from where I want to extract each and every character individually.
As i want something like THIS OUTPUT and so on.
What would be the appropriate approach to do this using OpenCV and python?
A short addition to Amitay's awesome answer. You should negate the image using
cv2.THRESH_BINARY_INV
to capture black letters on white paper.
Another idea could be the MSER blob detector like that:
img = cv2.imread('path to image')
(h, w) = img.shape[:2]
image_size = h*w
mser = cv2.MSER_create()
mser.setMaxArea(image_size/2)
mser.setMinArea(10)
gray = cv2.cvtColor(filtered, cv2.COLOR_BGR2GRAY) #Converting to GrayScale
_, bw = cv2.threshold(gray, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
regions, rects = mser.detectRegions(bw)
# With the rects you can e.g. crop the letters
for (x, y, w, h) in rects:
cv2.rectangle(img, (x, y), (x+w, y+h), color=(255, 0, 255), thickness=1)
This also leads to a full letter recognition.
You can do the following ( opencv 3.0 and aboove)
Run Otsu thresholding on the image (http://docs.opencv.org/3.2.0/d7/d4d/tutorial_py_thresholding.html)
Run connected component labeling with stats on the threshold images.(How to use openCV's connected components with stats in python?)
For each connected component take the bounding box using the stat you got from step 2 which has for each one of the comoneonts the follwing information (cv2.CC_STAT_LEFT cv2.CC_STAT_TOP cv2.CC_STAT_WIDTH cv2.CC_STAT_HEIGHT)
Using the bounding box crop the component from the original image.

Doing OCR to identify text written on trucks/cars or other vehicles

I am new to the world of Computer Vision.
I am trying to use Tesseract to detect numbers written on the side of trucks.
So for this example, I would like to see CMA CGM as the output.
I fed this image to Tesseract via command line
tesseract image.JPG out -psm 6
but it yielded a blank file.
Then I read the documentation of Tesserocr (python wrapper of Tesseract) and tried the following code
with PyTessBaseAPI() as api:
api.SetImage(image)
boxes = api.GetComponentImages(RIL.TEXTLINE, True)
print 'Found {} textline image components.'.format(len(boxes))
for i, (im, box, _, _) in enumerate(boxes):
# im is a PIL image object
# box is a dict with x, y, w and h keys
api.SetRectangle(box['x'], box['y'], box['w'], box['h'])
ocrResult = api.GetUTF8Text()
conf = api.MeanTextConf()
print (u"Box[{0}]: x={x}, y={y}, w={w}, h={h}, "
"confidence: {1}, text: {2}").format(i, conf, ocrResult, **box)
and again it was not able to read any characters in the image.
My question is how should I go about solving this problem? ( I am not looking for a ready made code, but approach on how to go about solving this problem).
Would I need to train tesseract with sample images or can I just write code using existing libraries to somehow detect the co-ordinates of the truck and try to do OCR only within the boundaries of the truck?
Tesseract expects document-only images, but you have non-document objects in your image. You need a sophisticated segmentation(then probably some image processing) process before feeding it to Tesseract-OCR.
I have a three-step solution
Take the part of the image you want to recognize
Apply Gaussian-blur
Apply simple-thresholding
You can use a range to get the part of the image.
For instance, if you select the
height range as: from (int(h/4) + 40 to int(h/2)-20)
width range as: from int(w/2) to int((w*3)/4)
Result
Take Part
Gaussian
Threshold
Pytesseract
CMA CGM
Code:
import cv2
import pytesseract
img = cv2.imread('YizU3.jpg')
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
(h, w) = gry.shape[:2]
gry = gry[int(h/4) + 40:int(h/2)-20, int(w/2):int((w*3)/4)]
blr = cv2.GaussianBlur(gry, (3, 3), 0)
thr = cv2.threshold(gry, 128, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
txt = pytesseract.image_to_string(thr)
print(txt)
cv2.imshow("thr", thr)
cv2.waitKey(0)

Search image for a certain colour and return the coordinates of blocks of that colour

Is there any library/program available in Python 2.7 that enables me to do this? I am a beginner in Python and I have to write a program that has to scan through a huge amount of images and detect all the position of a specified colour. I wonder is there any simple way to do this in Python?
from PIL import Image
img = Image.open('example.png')
pixels_count = 0
for x in xrange(img.size[0]):
for y in xrange(img.size[1]):
if img.getpixel((x, y)) == (255, 255, 255):
pixels_count += 1
print pixels_count

Draw a point on a raster image from CLI?

HOw do I draw a point on an image with ImageMagick (or some other linux CLI tool)? I tried:
convert tension_00.png -pointsize 100 -fill black -draw 'point 10,10' tension_001.png
I doesn't give error, but I can't find a point on the processed image.
Oh I solved it with pygames (that is from python script):
import pygame
img = pygame.image.load('tension_00.png')
pygame.draw.circle(img, (1, 1, 1), (600,600), 50) # Surface, color, pos, radius, width=0
pygame.image.save(img, 'test.png')