I am unable print colored text - python-3.x

I am unable to print the text in Orange colored.I identified the edges of the image and then printed a text on it.
%matplotlib inline
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('ind_maharashtra.png',0)
edges = cv2.Canny(img,100,20)
cv2.imwrite('Edged_img.jpg',edges)
#plt.subplot(121)
img1 = cv2.imread('Edged_img.jpg',0)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img1,'JAI MAHARASHTRA !!',(70,150), font, 0.7,(255,69,0),2,cv2.LINE_8)
cv2.imshow('Maharashtra Map',img1)
#cv2.imshow('Maharashtra Map',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

The problem is that the image on which you are trying to draw ( the image named img1) is a gray-scale image since the 2nd argument of cv2.imread is 0 in the following line:
img1 = cv2.imread('Edged_img.jpg',0)
You have 2 options to fix this issue. First one is to load the image as a color image as follows:
img1 = cv2.imread('Edged_img.jpg')
Alternatively, if you want your canvas to have a gray-ish look, you can just replicate the single channel to form a 3 channel image as follows:
img1 = cv2.imread('Edged_img.jpg', 0)
img1 = cv2.cvtColor(img1, cv2.COLOR_GRAY2BGR)

You are loading your jpg in grayscale, so you will only be able to write grayscale to img1
OpenCV Imread docs
change this line
img1 = cv2.imread('Edged_img.jpg',0)
to
img1 = cv2.imread('Edged_img.jpg',1)
As you can see from the above linked docs, using these numbers is OK but you are actually setting a flag, so you could use the flag definition to make your code clearer. Coincidentally, if you had used the flags you would likely not have had this issue.
You can change your line to
img1 = cv2.imread('Edged_img', cv2.IMREAD_COLOR)
Look how much clearer, and understandable that is. Especially when you come back to this code/hand it over to another developer in a few months time.

Related

Color diffusion when merging multiple images in a folder using PIL in python

I have set of 17 images and one of them has a highlighted pixel for my use. But, when I merge these 17 images, I get the color but it diffuses out of the pixel boundaries and I start seeing some colored pixel in black background.
I am using PIL library for the merging. I am attaching my code and the images for the reference. Any help would be appreciated.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# Cretaing the Pixel array
from PIL import Image
from PIL import ImageColor
img_path = '/Volumes/MY_PASSPORT/JRF/cancer_genome/gopal_gen/png_files/'
image_list = []
for entry in os.listdir(img_path):
if entry.endswith('.png'):
entry = int(entry.rstrip('.csv.png'))
image_list.append(entry)
image_list.sort()
list_img = []
for j in range(len(image_list)):
stuff = str(image_list[j])+'.csv.png'
list_img.append(stuff)
#print(list_img[0])
images = [Image.open(img_path+x) for x in list_img]
widths, heights = zip(*(i.size for i in images))
total_width = sum(widths)
max_height = max(heights)
#print(total_width, max_height)
new_im = Image.new('RGB', (total_width, max_height))
x_offset = 0
for im in images:
new_im.paste(im, (x_offset,0))
#print(im.size)
x_offset += im.size[0]
#print(x_offset)
new_im.save(img_path+'final_result_image.jpg')
Here is the combined image:
The third column has a pixel highlighted.
Here is the zoomed in part with the problem.
The JPEG format is lossy - it is allowed to change your pixels to make the file smaller. If your image is a conventional photo of a real-life scene, this doesn't normally matter. If your data is a blocky, computer-generated image, or a set of classes from a classification process, it can go horribly wrong if you use JPEG.
So, the answer is to use PNG (or potentially TIFF) format for images that need to be lossless.

What should I do to recognize digits from an seven segment display?

I'am working on a project to take pictures of the electricity meter reading and process the image to recognize the numbers and upload it to the cloud.
import cv2
import numpy as np
from matplotlib import pyplot as plt
from PIL import Image
image = cv2.imread('meter1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow('Original image',image)
cv2.imshow('Gray image', gray)
threshold = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 83, 5)
cv2.imshow('Adaptive Gaussian', threshold)
cv2.imwrite('Binary.png',threshold)
cv2.waitKey(0)
cv2.destroyAllWindows()
This is the code I have written so far which converts RGB image to grayscale and then used adaptive thresholding
This the image I used
What should I do next? Should I use tesseract OCR ? What are the ways to extract these digits or numbers
This is the image I got after running the code
Please help on how to proceed from this stage
Just check a point (or mean of a small ROI inside a segment) in each segment to recognize which digit is displayed.

How do you change the color of specified pixels in an image?

I want to be able to detect a certain area of pixels based on their RGB values and change them to some other color (not black/white).
I have tried changing these values in the code, but my resulting images always show black pixels replacing the specified locations:
pixelMap[i,j]= (255,255,255)
from PIL import Image
im = Image.open('Bird.jpg')
pixelMap = im.load()
img = Image.new(im.mode, im.size)
pixelsNew = img.load()
for i in range(img.size[0]):
for j in range(img.size[1]):
toup = pixelMap[i,j]
if(int(toup[0]>175) and int(toup[1]<100 and int(toup[2])<100) ):
pixelMap[i,j]= (255,255,255)
else:
pixelsNew[i,j] = pixelMap[i,j]
img.show()
You will find that iterating over images with Python loops is really slow and should get in the habit of using Numpy or optimised OpenCV or skimage code.
So, starting with this image:
from PIL import Image
import numpy as np
# Open image
im = Image.open('bird.jpg')
# Make into Numpy array
imnp = np.array(im)
# Make all reddish pixels white
imnp[(imnp[:,:,0]>170) & (imnp[:,:,1]<100) & (imnp[:,:,2]<100)] = [255,255,255]
# Convert back to PIL and save
Image.fromarray(imnp).save('result.jpg')
It looks like a tiny bug:
Instead of: pixelMap[i,j]= (255,255,255)
Use: pixelsNew[i,j] = (255,255,255)

Converting PNG PIL Image into OpenCV Image replaces transparency with black background

When I try to convert PNG type PIL Image into OpenCV Image, transparent background at PNG turns into black background. How can I keep the transparent background in OpenCV Image object.
Here is the code piece :
# PIL Image object which holds a transparent background png image.
pil_img = Image.open(ioFile).convert('RGBA')
pil_img.show()
# I use numpy to convert the pil_image into a numpy array
numpy_image = np.array(pil_img)
# I convert to a openCV2 image, notice the COLOR_RGB2BGR which means that
# the color is converted from RGBA to BGR format
opencvImage = cv2.cvtColor(numpy_image, cv2.COLOR_RGBA2BGRA)
#
#(I commented below lines, to show that I tried them but did not work.)
#
# opencvImage = cv2.cvtColor(numpy_image, cv2.IMREAD_UNCHANGED)
# opencvImage = cv2.cvtColor(numpy_image, cv2.COLOR_RGB2BGR)
showImage(opencvImage)
The last line of code piece shows an image with black background. I probably choose the wrong convert method and, could not find the proper one.
You can use this code for save transparency when converting.
To convert (with Alpha) from Pillow image to OpenCv image:
You can manually change the color order.
import cv2
from PIL import Image
import numpy as np
pillowImage = Image.open('picturePath.png').convert('RGBA')
img = np.array(pillowImage) # 'img' Color order: RGBA
red = img[:,:,0].copy() # Copy R from RGBA
img[:,:,0] = img[:,:,2].copy() # Copy B to first order. Color order: BGBA
img[:,:,2] = red # Copy R to the third order. Color order: BGRA
opencvImage = img # img is OpenCV variable

Wrong colours with cv2.imdecode (python opencv)

I try to display the image located here: http://skyservice.pha.jhu.edu/DR12/ImgCutout/getjpeg.aspx?ra=118.70299999999999&dec=45.721000000000004&width=10&height=10&scale=0.6
The image looks like this:
I use this code:
import matplotlib.pyplot as plt
import numpy as np
import urllib
import cv2
url = 'http://skyservice.pha.jhu.edu/DR12/ImgCutout/getjpeg.aspx?ra=118.70299999999999&dec=45.721000000000004&width=10&height=10&scale=0.6'
def url_to_image(url):
resp = urllib.request.urlopen(url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR)
return image
img = url_to_image(url)
plt.imshow(img)
And it displays this:
Where all colours are too blue. I have tried various possibilities to change cv2.IMREAD_COLOR with values found in the manual, on StackOverflow or elsewhere on the net, like -1, 0, 1, cv2.COLOR_BGR2RGB, ... but I haven't been able to get the right colours. I have tried cv2.COLOR_BGR2GRAY, it didn't even show in gray scales. I even tried this answer, but cv2.CV_LOAD_IMAGE_COLORdoesn't seem to exist anymore...
Is there a correct value of cv2.imdecode() flag, or a special colormap of plt.imshow(), which would give me the initial colours?
Thanks to Mark Setchell, it now works. I quote him:
matplotlib requires RGB ordering whereas OpenCV (perversely) uses BGR
Therefore, the correct code is
def url_to_image(url):
resp = urllib.request.urlopen(url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
imageBGR = cv2.imdecode(image, cv2.IMREAD_COLOR)
imageRGB = cv2.cvtColor(imageBGR , cv2.COLOR_BGR2RGB)
return image

Resources