life, technology, thoughts Prasanna Kumar life, technology, thoughts Prasanna Kumar

Search engines doesn't work

For design(and dev): Sometimes default search engines(google/DDG) doesn't work at all.

For design(and dev) related queries, sometimes default search engines(google/DDG) doesn't work at all.

Now a days I directly go to:

* Hacker News search
* Orielly book search
* Internet archive book/documents search
* Stackexchange(of course)

Better, search what you want on Google;
Tools > select custom time range > Select any time before 2008

* No SEO manipulated pages
* Plain html/text pages
* More often takes you in the right path.
* This won't work in YouTube.(new content creators can't monetise then)

Read More
life, work, technology, applications Prasanna Kumar life, work, technology, applications Prasanna Kumar

Faster way to do emails

Want to try new way of doing emails, have some time to burn, want to have fun:
Why not try Mutt? It’s been there since 1995


Every one wants to do faster emails now! — but why? that is an altogether different question, as in, why would any one want a lite-help-desk-software for managing emails?

But hey Hey.com[1]

To every one who is eagerly waiting to get an invite from Hey.com
If your question is: How is this problem being solved now? How are power email users managing emails?
Want to try new way of doing emails, have some time to burn, want to have fun:
Why not try Mutt? [2]
It is free under General Public License, been there since 1995.Refer [5][6]

Typical Mutt setup:
Your fav terminal > Mutt > Vim[3] > GnuPG[4]

In a way, it is a faster way to do emails:

* Entirely command line.
* Plain text only
* Key bindings that you can learn and master
* Configure your favourite editor to compose(a good opportunity to learn Vim)
* GPG end-to-end encryption support

Caveats

* Take just minutes to get it up and running, but configuring perfectly will a be work in progress.[4]
* High learning curve, but hey any thing worth doing is.

[1] https://hey.com/
[2] http://www.mutt.org/
[3] https://www.vim.org/
[4] https://gnupg.org/
[5] https://stevelosh.com/blog/2012/10/the-homely-mutt/
[6] https://wiki.archlinux.org/index.php/Mutt
[7] Mutt in action: Video


After thoughts:

Quoting Hey.com from this link:

Either they rely on everyone using the same service/app (good luck converting everyone you email with to use the same setup as you!). Or the emails aren’t really emails, but links to a website where the encryption is then applied. Or you use a clunky external tool to encrypt and decrypt the messages (like PGP). This really only works if you’re willing to give up on email as we commonly understand it. If you absolutely must have end-to-end encrypted email, checkout something like ProtonMail. 

This posturing, I don’t understand, Hey.com’s narrative is don’t believe in Google, but believe us, why should anyone? — without end-to-end encryption.

Users must control the encryption. That is why end-to-end encryption(PGP) works and has been around for more than 25 years.

PGP is a difficult concept to grasp at first, but once you wrap your head around it, you’ll feel more liberated and safe.

It is not clunky? Is terminal window clunky?

For anyone who wants to try PGP on a mac try GPGtools.
They have made a commendable job of making encryption and decryption of emails, and files easy.

This is how GPG integrated email looks on the native Apple mail client.

All emails are encrypted and signed using GPG. You own the encryption keys.

All emails are encrypted and signed using GPG. You own the encryption keys.

Encrypt and decrypt files, folders and disks with a click

Encrypt and decrypt files, folders and disks with a click

Read More
technology Prasanna Kumar technology Prasanna Kumar

Extracting colour palettes from an image

Trying out Colorthief a python package extract colour palettes from an image.

Trying out Colorthief a python package extract colour palettes from an image.

Was reading through an enhancement request on Pillow's github page. Currently Pillow does not give an built-in way to identify all dominant colours on an image. The suggestion was to port "Colorthief" package into Pillow.

Trying Colorthief.

Fairly simple and direct, pip install it.
Follow the instructions here and with little bit of help on how to map numpy arrays it is easy.

 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
from colorthief import ColorThief
import numpy as np
import matplotlib.pyplot as plt

color_thief = ColorThief('/home/pk/Desktop/bd.png')
dominant_color = color_thief.get_color(quality=1)

"""dominant_color
0 = 147
1 = 66
2 = 46"""

color_palette = color_thief.get_palette(color_count=12)
color_palette = np.asarray(color_palette)[np.newaxis, :, :]
"""
Color_palette = 0 = <numpy.array at 0x7f64b92173f0[6x1]>
0 = [136  53  35]
1 = [40 14 22]
2 = [195 117  89]
3 = [232 168 152]
4 = [213 130 107]
5 = [209 136 134]"""

plt.imshow(color_palette);
plt.axis('off');
plt.show();
pallette.png
Read More
technology, photography Prasanna Kumar technology, photography Prasanna Kumar

Color Image into Grayscale using Python Image Processing Libraries | An Exploration

Exploring monochrome image processing using various Python image processing libraries

Processing Libraries used:

Libraries for image data wrangling:

From SciPy:

To get started, lets access the image file and bring it inside our script. Let us use the python os module to access and read the file into the script

We will also be importing "Image" module from Pillow(PIL) library

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
'''Exploring grayscale with Python using PIL, Skimage, NumPy and Matplotlib Libraries'''

import os
from PIL import Image, ImageColor, ImageOps
from skimage import color
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.style as style
import matplotlib.image as mpimg
from exception import IOError

'''Opening an image using Python's os module'''

path = os.path.join(os.path.expanduser('~'), 'Desktop','color','img-4.jpg')
img = Image.open(path)
img.show()

Lets read the image properties using PIL.image functions. To check if the right image is read, let's open it in the default image previewer of your OS.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
img = Image.open(path)
img.show() #preview the image in the default image editor of your OS

'''Image Properties'''
print("filename:",img.filename)
print("format:", img.format)
print("mode:", img.mode)
print("size:", img.size)
print("width*height", img.width, "*", img.height)
print("palette:", img.palette)
print("Image Info:", img.info)

The image properties

  • filename: /home/pk/Desktop/color/img-4.jpg
  • format: JPEG * mode: RGB
  • size: (900, 601)
  • width*height: 900 * 601
  • palette: None
  • imgInfo: dict_keys(['exif', 'dpi', 'photoshop', 'adobe', 'adobe_transform', 'icc_profile'])

Converting to Grayscale

Method 1: Averaging the R,G,B values.(non-linear)

This is the most basic of all grayscale conversion method. We take the average of R,G,B values of each pixel to arrive at a single value(ranging from 0 (black) to 255 (white).

As quoted here :

Some computer systems have computed brightness using (R+G+B)/3. This is at odds with the properties of human vision


Method 1: Averaging - R,G,B values 

Y = (R+G+B)/3

1
2
3
4
5
6
7
8
9
"""Method 1 - Averaging - R,G,B values """ 

#Python's Lambda(anonymous) expression. Apply simple math and convert to a list(of pixles)

AllPixels = list(map(lambda x: int((x[0] + x[1] + x[2])/3), list(img.getdata()))) 
GreyscaleImg1 = Image.new("L", (img.size[0], img.size[1]), 255)   #instantiate an image
GreyscaleImg1.putdata(AllPixels)   #Copies pixel list to this image
GreyscaleImg1.show()               #preview image
plotHist(GreyscaleImg1,"Averaging")  #plot a histogram

The human eye always interprets different colors in a different way. The weights ranging in the order of Green, Red and Blue.

Taking into consideration the color perception, we have methods 2 and 3 below.

Method 2: LUMA-REC-601(non-linear)

Again quoting Charles Poynton,

If three sources appear red, green and blue, and have the same radiance in the visible spectrum, then the green will appear the brightest of the three because the luminous efficiency function peaks in the green region of the spectrum. The red will appear less bright, and the blue will be the darkest of the three. As a consequence of the luminous efficiency function, all saturated blue colors are quite dark and all saturated yellows are quite light. If luminance is computed from red, green and blue, the coefficients will be a function of the particular red, green and blue spectral weighting functions employed, but the green coefficient will be quite large, the red will have an intermediate value, and the blue coefficient will be the smallest of the three.


Method 2 - LUMA-REC-601

Y = ( R * 299/1000 + G * 587/1000 + B * 114/1000 )

1
2
3
4
5
6
7
8
9
""""""Method 2 - LUMA-REC-601"""  """ 

#Python's Lambda(anonymous) expression. Apply simple math and convert to a list(of pixles)

AllPixels = list(map(lambda x: int(x[0]*(299/1000) + x[1]*(587/1000) + x[2]*(114/1000)), list(img.getdata())))
GreyscaleImg2 = Image.new("L", (img.size[0], img.size[1]), 255)   #instantiate an image
GreyscaleImg2.putdata(AllPixels)   #Copies pixel list to this image
GreyscaleImg2.show()               #preview image
plotHist(GreyscaleImg2,"REC-601")  #plot a histogram

The PIL image module has a convert function that helps to convert an image from one mode to another. To convert to grayscale, pass in "L" (luminance) as a mode parameter. When translating a color image to black and white (mode “L”), the library uses the ITU-R 601-2 luma transform

1
2
3
4
#When translating a color image to black and white (mode “L”), the library uses the ITU-R 601-2 luma transform:

grayImg = img.convert('L')
grayImg.show()

Learn more about LUMA REC.601 here.

Method 3 - LUMA-REC.709(non-linear)

Both REC.601 and REC.709 considers the difference in color perception( and hence different coefficients for R,G, B). But the major difference is as follows:

Quoting Charles Poynton, with respect to REC.60:

The coefficients 0.299, 0.587 and 0.114 properly computed luminance for monitors having phosphors that were contemporary at the introduction of NTSC television in 1953. However, these coefficients do not accurately compute luminance for contemporary monitors

Where as REC.709:

Contemporary CRT phosphors are standardized in Rec. 709 [9], to be described in section 17. The weights to compute true CIE luminance from linear red, green and blue (indicated without prime symbols), for the Rec. 709, are these:



Method 2 - LUMA-REC.709

Y = 0.2125 * R + 0.7154 * G + 0.0721 * B

1
2
3
4
5
6
7
8
9
""""""Method 3 - LUMA-REC-709"""  """ 

#Python's Lambda(anonymous) expression. Apply simple math and convert to a list(of pixles)

AllPixels = list(map(lambda x: int(x[0]*(212/1000) + x[1]*(715/1000) + x[2]*(72/1000)), list(img.getdata())))
GreyscaleImg3 = Image.new("L", (img.size[0], img.size[1]), 255)   #instantiate an image
GreyscaleImg3.putdata(AllPixels)   #Copies pixel list to this image
GreyscaleImg3.show()               #preview image
plotHist(GreyscaleImg3,"REC-709")  #plot a histogram

Let’s dig down to see, how the math works at the pixel level:

grayscale-pixels-python-REC-709.png

The results from the grayscale conversion methods:


 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
def plotHist(grayImg, title):
   ImagingCore= grayImg.getdata()
   print(ImagingCore)  #<ImagingCore object at 0x7f952e28aa10>
   print(type(ImagingCore))   #<class 'ImagingCore'>
   print(grayImg.getextrema())    #(0, 255)
   
   #Follwing returns a flat list of pixel values(ranging from 0-255). We'll convert these values into an array down below
   GrayPixels=list(grayImg.getdata()) 
   print(type(GrayPixels))    #<class 'list'>
   
   # convert the list into an array. Matplotlib accepts array as a parameter to plot histogram
   GrayPixelsArray = np.array(GrayPixels) 
   
   print (GrayPixelsArray.size) #540900 i.e width*height: 900 * 601
   print (GrayPixelsArray.shape) #(540900,)
   print (GrayPixelsArray.dtype) #int64
   print (GrayPixelsArray.ndim) #1-D array
   print(np.mean(GrayPixelsArray), 
         np.median(GrayPixelsArray),
         np.std(GrayPixelsArray),
         np.max(GrayPixelsArray), 
         np.min(GrayPixelsArray))    #64.90450730264374 66.0 31.959808127905852 255 0
   plt.style.use('Solarize_Light2')      
   plt.hist(GrayPixelsArray, bins = 255)
   plt.title(title) 
   plt.show()

Image Statistics:
+------------+---------+---------+--------+------+-----+
| Grayscale  |  Mean   | Median  |  Std   | Max  | Min |
+------------+---------+---------+--------+------+-----+
+------------+---------+---------+--------+------+-----+
| Averaging  | 64.90   |  66.0   | 31.95  | 255  |  0  |
+------------+---------+---------+--------+------+-----+
|  REC-601   | 77.76   |  76.0   | 41.38  | 255  |  0  |
+------------+---------+---------+--------+------+-----+
|  REC-709   | 86.23   |  82.0   | 47.94  | 254  |  0  |
+------------+---------+---------+--------+------+-----+

Grayscale conversion using Scikit-image processing library

We will process the images using NumPy. NumPy is fast and easy while working with multi-dimensional arrays.

For instance an RGB image of dimensions M X N with their R,G,B channels are represented as a 3-D array(M,N,3). Similarly a grayscale image is represented as 2-D array(M,N). NumPy is fast and easy when it comes to doing calculations on big arrays(large images).

We’ll use plotting functions from Matplotlib to plot and view the processed image.

To convert to grayscale(non-linear):

  1. We’ll be using the inbuilt rgb2gray from the color module. rgb2gray uses REC.709. for the conversion

  2. We’ll also manually do the REC.709 conversion calculation by working on the numpy.ndarray objects

 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
import os
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from skimage import color, io, data
from skimage.viewer import ImageViewer
from PyQt5 import QtCore, QtGui, QtWidgets

img = io.imread('/home/pk/Desktop/color/img-4.jpg')  #Fetch the image into the script

"""Reading the properties of the image"""

#plt.imshow(img)
#plt.show()
#print(img)    #Prints RGB values of each pixel across W*H as a 3D matrix(M,N,3)
#print(type(img))    #<class 'numpy.ndarray'>
#print(img.shape)    #(601, 900, 3)


"""Splitting the image into R,G,B Channels"""

R = img[:, :, 0]
G = img[:, :, 1]
B = img[:, :, 2]
Gray = color.rgb2gray(img) # REC.709 | Y = 0.2125 R + 0.7154 G + 0.0721 B 
#Gray = (R*0.212)+(G*0.715)+(B*0.072) # or do the conversion math across 3 channels

## we shall use matplotlib to display the channels

fig, ((ax1, ax2), (ax3,ax4)) = plt.subplots(nrows=2, ncols=2, figsize=(20,10))

ax1.imshow(R,cmap=plt.cm.Reds)
ax1.set_title("RED Channel")

ax2.imshow(G,cmap=plt.cm.Greens)
ax2.set_title("GREEN Channel")

ax3.imshow(B,cmap=plt.cm.Blues)
ax3.set_title("BLUE Channel")

ax4.imshow(Gray, cmap="gray")
ax4.set_title("GRAYSCALE: rgb2gray(uses REC.709) ")

plt.show()
RGB image numpy.ndarray representation.

RGB image numpy.ndarray representation.

Plot of red, green, blue, and gray conversions.

scikit-RGB-Grayscale-output1.jpeg

Converting to GrayScale: The right way by linearization of sRGB by applying inverse gamma function.

All RGB images are gamma encoded.

Gamma encoding of images is used to optimize the usage of bits when encoding an image, or bandwidth used to transport an image, by taking advantage of the non-linear manner in which humans perceive light and color.

Where as Luminance is:

Luminance is a spectrally weighted but otherwise linear measure of light. The spectral weighting is based on how human trichromatic vision perceives different wavelengths of light.

The correct luminance value is calculated(by linearization using inverse gamma function) using the following steps:

linearization-of-RGB-inverse-gamma.png
 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
""" Applying Linearisation on a gamma encoded sRGB Image.
    In vChannel, Channel is color channel as in vR, VG, vB
"""
def linearize(vChannel):
    vChannelFlat = vChannel.ravel()  #flatten 2-D array into 1-D array
    vChannelLinear= []
    for i in vChannelFlat:
        if i <= 0.040:
            i = (i/12.92)
            vChannelLinear.append(i)
        else:
            i = pow((i+0.055)/(1.055),2.4)
            vChannelLinear.append(i)
    return np.asarray(vChannelLinear).reshape(601,900)

R = img[:, :, 0]
G = img[:, :, 1]
B = img[:, :, 2]

vR, vG, vB = R/255, G/255, B/255

"Calculating Relative Luminance"

Ylin = (0.216* linearize(vR)) + (0.715* linearize(vG)) + (0.072* linearize(vB)) 
YlinFlat = Ylin.ravel()  #converting into 1-D array to plot histogram
Gray = color.rgb2gray(img)  #scikit rgb2gray function(non-linearized)
Grayflat = Gray.ravel()

fig, ((ax1,ax2),(ax3,ax4)) = plt.subplots(2,2,figsize=(5,5))
ax1.imshow(Ylin, cmap="gray")
ax1.set_title("Linear")
ax2.imshow(Gray,cmap ="gray")
ax2.set_title("Non-linear")
ax3.hist(YlinFlat, bins = 255)  #compare the histograms of linearized & non-linearized
ax4.hist(Grayflat, bins = 255)
plt.show()

References:

  1. Some great answers from Stackoverflow: here, here and here.
  2. A great post on gamma correction.
  3. Another great source on linear transformation.

Read More
work, applications, technology Prasanna Kumar work, applications, technology Prasanna Kumar

VIM

It takes a decade to master VIM they say. Mine is just beginning. I've seen how powerful the tool could be. It's like having a nitro boosters on fingers.

vim.png

It takes a decade to master VIM they say. Mine is just beginning. I've seen how powerful the tool could be. It's like having a nitro boosters on fingers.

Starting to get used to "navigating/moving around" the text.

h,j, k, l

Ww, Bb

gg, G

3gg, 10gg

ctrl f, ctrl b

shift $, shift ^

Read More
life, technology Prasanna Kumar life, technology Prasanna Kumar

Hello World from LINUX

My linux system is so humble and simple in its config.

I got a refurbished DELL Optiplex 9010, stripped all its fancy parts, loaded a 2010, Intel Pentium G2010 Dual Core processors with 128 GB SSD and runs on Ubuntu 18.04.3 LTS.

My current Macbook pro(2017) is taking a heavy pounding. Keyboard issues, slow processing speed, strange reboots with scary kernal warning messages.

May be I'm like too much of a task master.

So decided to shift the load.

  1. Personal and coding related work to linux.
  2. Professional work - Photography, design and video editing on the MacBook. I can't live without the Adobe Suite and FCPX

My linux system is so humble and simple in its config. I got a refurbished DELL Optiplex 9010, stripped all its fancy parts, loaded a 2010, Intel Pentium G2010 Dual Core processors with 128 GB SSD and runs on Ubuntu 18.04.3 LTS.

My desktop and some of the apps i’m getting used to.

My desktop and some of the apps i’m getting used to.

my-work-station.jpg
Read More
technology Prasanna Kumar technology Prasanna Kumar

Giving it back

Over the years, there have been a lot of software applications and online communities — open source to be specific — which I’ve benefited from directly by using them for work and indirectly because each one of them stood and are still standing up to something very specific — and that is wonderfully inspiring.

internet-archive-donation

Over the years, there have been a lot of software applications and online communities — open source to be specific — which I’ve benefited from directly by using them for work and indirectly because each one of them stood and are still standing up to something very specific — and that is wonderfully inspiring.

It is only after subscribing to few of the core mailing lists it dawned on me that, help, however small, can help move the movement an inch forward.

As a first step, I’ve decided to contribute $1 every month to the following apps and communities



Please do check your computer: make a list of all the open-source applications that you are using — I emailed this question to few of my friends; On a average they use 4 applications/communities that are on open-source/public domain.

Did you find any application that you can live/work without? Go make a donation. Contribute!


Read More
applications, life, work, technology Prasanna Kumar applications, life, work, technology Prasanna Kumar

Tools of the Trade

The following are the tools and applications that helps me get the job done; both personally and professionally(photography, video and design)


The following are the tools and applications that helps me get the job done; both personally and professionally(photography, video and design)

Hardware

Workstation

  • MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)
  • Dell 21.5 inch (54.6 cm) Ultra Thin Bezel LED Monitor
  • Bose QuietControl 30, Noise cancellation headphones

Photography

  • Godox AD600B(studio light)
  • Godox V860 N(camera flash) * 2
  • Zhiyun crane 2
  • DJI Osmo Mobile 2
  • iPad mini 2 - 20% of my reading happens here with iBooks & Kindle app for iPad.

Software:

Creative Suite:

  • Photoshop CC
  • Lightroom CC
  • GIMP - for quick, lightweight photo edits.
  • Inkscape - vector design
  • Sketch - design
  • Final cut pro
  • Handbrake video transcoder
  • Apple Keynote

Writing & Research

  • Ulysses - Notemaking
  • LaTeX - for documentation
  • Brother 220 manual typewriter
  • Ember(now discontinued) - Capture screenshots, videos, and organize them under tags(visual research)
  • The Wayback machine lets you capture web pages and store it as an archive for reference and sharing.
  • Both Ember and The Wayback Machine are my humble attempt to try Zettelkasten.

Tasks

Storage:

  • Amazon drive - Backup for: personal projects, and photos on the iPhone
  • AWS S3 - Backup for professional projects

Fitness:

  • Garmin Forerunner 15 GPS watch.
  • Smashrun - Training and running intelligence integrated with Garmin Connect.

Music:

  • Apple Music
  • Panasonic Bahadur AM | FM radio - I live alone and gets too lonely in the mornings. Most of the time it is for just the white noise.
  • GPO vinyl record player

Communication:

  • Panasonic KX-TG1612 Cordless Phone - Landline for work-related communications.

Browsers:

  • Google Chrome
  • Tor - with duckduckgo; for ads-blocked privacy conscious browsing. Mostly used during focused research.

Read More