cannot read in image in colour in opencv python - python-2.7

I have just started to use Opencv using python in windows(PyCharm IDE).
I tried to read a color image. But it got displayed in Grayscale. So I tried to convert it as below:
import cv2
img = cv2.imread('C:\Ai.jpg', 0)
b,g,r = cv2.split(img)
rgb = cv2.merge([r,g,b])
cv2.imshow('image', img)
cv2.imshow('rgb image',rgb)
cv2.waitKey(0)
cv2.destroyAllWindows()
But i am getting an error:
"b, g, r = cv2.split(img) ValueError: need more than 1 value to
unpack"
Can you guys please help me out?
Thanks in advance.

There is a problem in the second line of your code img = cv2.imread('C:\Ai.jpg', 0), as per the documentation, 0 value corresponds to cv2.IMREAD_GRAYSCALE, This is the reason why you are getting a grayscale image. You may want to change it to 1 if you want to load it in RGB color space or -1 if you want to include any other channel like alpha channel which is encoded along with the image.
And b,g,r = cv2.split(img) was raising an error because img at that point of time is a grayscale image which had only one channel, and it is impossible to split a 1 channel image to 3 respective channels.
Your final snippet may look like this:
import cv2
# Reading the image in RGB mode
img = cv2.imread('C:\Ai.jpg', 1)
# No need of following lines:
# b,g,r = cv2.split(img)
# rgb = cv2.merge([r,g,b])
# cv2.imshow('rgb image',rgb)
# Displaying the image
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Try this solution
Read and convert image into RGB format:
If you have a color image and reading it using OpenCV. First, convert it in RGB colour format
image = cv2.imread(C:\Ai.jpg') #cv2 reading image in BGR
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) #convert it into RGB format
To display it we can use cv2.imshow, matplotlib or PIL as follows
import matplotlib.pyplot as plt
%matplotlib inline
from PIL import Image
Now print using matplotlib:
plt.imshow(image)
print using PIL
Image.fromarray(image)

Related

Why doesn't pytesseract recognize any text in this image?

I have this image input image on which I am attempting to apply text detection and ocr,
however even after preprocessing (binary thresholding etc) pytesseract doesn't return any output. The purpose of text detection is to improve the ocr output, I'm not too concerned with obtaining bounding boxes.
Here is my code below:
image = cv2.imread('image.jpg')
grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret,thresh1 = cv2.threshold(grey,127,255,cv2.THRESH_BINARY)
image = pytesseract.image_to_data(thresh1, output_type=Output.DICT)
image = cv2.bitwise_not(image)
Inspecting the results there is none to nonsensical output, is there anyway to improve this?
Try this code:
import pytesseract
import cv2
image = cv2.imread('ccl6t.png')
pytesseract.pytesseract.tesseract_cmd = r'k:\Tesseract\tesseract.exe' #need change!
grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret,thresh1 = cv2.threshold(grey,127,255,cv2.THRESH_BINARY_INV)
cv2.imwrite('tresh.png', thresh1)
words = pytesseract.image_to_data(thresh1, lang='eng',config='--psm 3 --oem 1 ')
print(str(words))

Is there any problems in Image.open(os.path.join(origin_path,name)).convert('P')?

I changed some images in pascal dataset by opencv,then i need to convert them to P mode.
I used img = Image.open(os.path.join(origin_path,name)).convert('P') to convert RGB images to P mode.But the new image is a little strange.Why the color of new image is not smooth as the original?
Is it harmful to my training?How can i deal with it?
Original Image
New Image
Oh, I see. You want to modify the palette. You can do that like this:
#!/usr/bin/env python3
import numpy as np
from PIL import Image
# Load the source image
im = Image.open('original.png')
# Extract the palette into a Numpy array and reshape as 256 RGB triplets
palette = np.array(im.getpalette())
colorVectors = np.reshape(palette,(-1,3))
# Replace any palette entries consisting of [192,128,128] with yellow [255,255,0]
colorVectors[np.all(colorVectors==[192,128,128],axis=-1)] = [255,255,0]
# Put modified palette into image and save
im.putpalette(colorVectors.ravel().tolist())
im.save('result.png')
Original Image
Output Image
If you know you want to change a specific palette entry and you know that it is, say, entry 0, you can do:
#!/usr/bin/env python3
import numpy as np
from PIL import Image
# Load the source image
im = Image.open('original.png')
# Extract the palette into a Numpy array and reshape as 256 RGB triplets
palette = np.array(im.getpalette())
colorVectors = np.reshape(palette,(-1,3))
# Make palette entry 0 into magenta
colorVectors[0]=[255,0,255]
im.putpalette(colorVectors.ravel().tolist())
im.save('result.png')
Keywords: Python, PIL, Pillow, palette, palletised, PNG, modify palette, change palette, alter palette, replace palette, image, image processing.

segmentation of overlapping cells

The following python script should split overlapping cells apart which does work quite good. The problem is now that it also splits some of the cells apart which don't overlap with other cells. To make things clear to you i'll add my input image and the output image.
The input:input image
The output:
output image
Output image where I marked two "bad" segmented cells:Output image with marked errors
Thresholded image: Thresholded image
Does someone have an idea how to avoid this problem or is the whole approach not good enough to process these kind of images?
I am using the following piece of code to segment the cells:
from skimage.feature import peak_local_max
from skimage.morphology import watershed
from scipy import ndimage
import numpy as np
import cv2
# load the image and perform pyramid mean shift filtering
# to aid the thresholding step
image = cv2.imread('C:/Users/Root/Desktop/image13.jpg')
shifted = cv2.pyrMeanShiftFiltering(image, 41, 51)
# convert the mean shift image to grayscale, then apply
# Otsu's thresholding
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255,
cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
im = gray.copy()
D = ndimage.distance_transform_edt(thresh)
localMax = peak_local_max(D, indices=False, min_distance=3,
labels=thresh)
# perform a connected component analysis on the local peaks,
# using 8-connectivity, then apply the Watershed algorithm
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thresh)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))
conts=[]
for label in np.unique(labels):
# if the label is zero, we are examining the 'background'
# so simply ignore it
if label == 0:
continue
# otherwise, allocate memory for the label region and draw
# it on the mask
mask = np.zeros(gray.shape, dtype="uint8")
mask[labels == label] = 255
# detect contours in the mask and grab the largest one
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[-2]
c = max(cnts, key=cv2.contourArea)
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
if cv2.contourArea(c) > 150:
#cv2.drawContours(image,c,-1,(0,255,0))
cv2.drawContours(image,[box],-1,(0,255,0))
cv2.imshow("output", image)
cv2.waitKey()

Splitting text and background as preprocess of OCR (Tesseract)

I am applying OCR against text in TV footage. (I am using Tesseact 3.x w/ C++)
I am trying to split text and background part as a preprocessing of OCR.
With usual footage, text and background is highly contrasted (such as white against black) so that modifying gamma would do the job.
However, this attached image (yellow text with background of orange/red sky) is giving me hard time to do preprocessing.
What would be a good way to split this yellow text from background?
Below is a simple solution by using Python 2.7, OpenCV 3.2.0 and Tesseract 4.0.0a. Convert Python to C++ for OpenCV should be not difficult, then call tesseract API to perform OCR.
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
def show(title, img, color=True):
if color:
plt.imshow(img[:,:,::-1]), plt.title(title), plt.show()
else:
plt.imshow(img, cmap='gray'), plt.title(title), plt.show()
def ocr(img):
# I used a version of OpenCV with Tesseract binding. Modes set to:
# Page Segmentation mode (PSmode) = 11 (defualt = 3)
# OCR Enginer Mode (OEM) = 3 (defualt = 3)
tesser = cv2.text.OCRTesseract_create('C:/Program Files/Tesseract 4.0.0/tessdata/','eng', \
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',3,3)
retval = tesser.run(img, 0) # return text string type
print 'OCR Output: ' + retval
img = cv2.imread('./imagesStackoverflow/yellow_text.png')
show('original', img)
# apply GaussianBlur to smooth image, then threshholds yellow to white (255,255, 255)
# and sets the rest to black(0,0,0)
img = cv2.GaussianBlur(img,(5,5), 1) # smooth image
mask = cv2.inRange(img,(40,180,200),(70,220,240)) # filter out yellow color range, low and high range
show('mask', mask, False)
# invert the image to have text black-in-white
res = 255 - mask
show('result', res, False)
# pass to tesseract to perform OCR
ocr(res)
Processed Images and OCR Output (see last line in image):
Hope this help.

Change origin of image coordinate system to bottom left instead of default top left

Is there a simple way of changing the origin of image co-ordinate system of OpenCV to bottom left? Using numpy for example? I am using OpenCv 2.4.12 and Python 2.7.
Related: Numpy flipped coordinate system, but this talks about just display. I want something which I can use consistently in my algorithm.
Update:
def imread(*args, **kwargs):
img = plt.imread(*args, **kwargs)
img = np.flipud(img)
return img
#read reference image using cv2.imread
imref=cv2.imread('D:\\users\\gayathri\\all\\new\\CoilA\\Resized_Results\\coilA_1.png',-1)
cv2.circle(imref, (0,0),30,(0,0,255),2,8,0)
cv2.imshow('imref',imref)
#read the same image using imread function
im=imread('D:\\users\\gayathri\\all\\new\\CoilA\\Resized_Results\\coilA_1.png',-1)
img= im.copy()
cv2.circle(img, (0,0),30,(0,0,255),2,8,0)
cv2.imshow('img',img)
Image read using cv2.imread:
Image flipped using imread function:
As seen the circle is drawn at the origin on upper left corner in both original and flipped image. But the image looks flipped which I do not desire.
Reverse the height (or column) pixels will get the result below.
import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
img = cv2.imread('./imagesStackoverflow/flip_body.png') # read as color image
flip = img[::-1,:,:] # revise height in (height, width, channel)
plt.imshow(img[:,:,::-1]), plt.title('original'), plt.show()
plt.imshow(flip[:,:,::-1]), plt.title('flip vertical'), plt.show()
plt.imshow(img[:,:,::-1]), plt.title('original with inverted y-axis'), plt.gca().invert_yaxis(), plt.show()
plt.imshow(flip[:,:,::-1]), plt.title('flip vertical with inverted y-axis'), plt.gca().invert_yaxis(), plt.show()
Output images:
Above included the one you intended to do?