0

I am trying to take an image and convert it to grayscale, adding some gaussian blur to that image, and detecting the edges. I am having trouble displaying the image with matplotlib's pyplot.

import cv2
import matplotlib.pyplot as plt

def read_image_and_print_dims(image_path):
    """Reads and returns image.
    Helper function to examine ow an image is represented"""

    #reading an image
    image=cv2.imread(image_path)
    #printing out some stats and plottin
    print('This image is ',type(image),' with dinmesions',image.shape)
    plt.subplot(2,2,3)
    plt.imshow(image)
    return image

image_path='fall-leaves.png'

img=read_image_and_print_dims(image_path)
#Make a blurred/smoothed version
def gaussian_blur(img,kernel_size):

    """Applies a Gaussian Noise Kernel"""
    print ('Inside Gaussian')

    return cv2.GaussianBlur(img,(kernel_size,kernel_size),4)

#Gray Scale Image
def grayscale(img):
    """Applies the Grayscale transform
        This will return an image with only one color channel
        but NOTE: to see the returned image as grayscale
        you should call plimshow(gray, cmap='gray')"""
    print ('Inside gray sale')
    return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


# gray scale it
greyscaled_image = grayscale(img)
plt.subplot(2, 2, 1)

plt.imshow(greyscaled_image, cmap='gray')

# smooth it a bit with Gaussian blur
kernal_size = 11
blur_gray = gaussian_blur(img, kernal_size)

plt.subplot(2, 2, 2)
plt.imshow(blur_gray)

cv2.waitKey(0)
cv2.destroyAllWindows()

While running above code in Pycharm it generates following message:

('This image is ', <type 'numpy.ndarray'>, ' with dinmesions', (320L, 400L, 3L))
Inside gray sale
Inside Gaussian

But it doesn't plot the image.

EDIT

I got it to display using plt.show. However, now I'm having a different problem. I obtained this figure from pyplot, but using cv2.imshow, I got these: top two images, bottom two images

This is my code for plt.show:

#REad Image
import numpy as np
import cv2
import matplotlib.pyplot as plt

def read_image_and_print_dims(image_path):
    """Reads and returns image.
    Helper function to examine ow an image is represented"""

    #reading an image
    image=cv2.imread(image_path)
    #printing out some stats and plottin
    print('This image is ',type(image),' with dinmesions',image.shape)
    plt.subplot(2,2,1)
    #cv2.imshow('Original Image',image)
    plt.imshow(image)
    return image

image_path='fall-leaves.png'

img=read_image_and_print_dims(image_path)
#Make a blurred/smoothed version
def gaussian_blur(img,kernel_size):

    """Applies a Gaussian Noise Kernel"""
    print ('Inside Gaussian')

    return cv2.GaussianBlur(img,(kernel_size,kernel_size),4)

#Gray Scale Image
def grayscale(img):
    """Applies the Grayscale transform
        This will return an image with only one color channel
        but NOTE: to see the returned image as grayscale
        you should call plimshow(gray, cmap='gray')"""
    print ('Inside gray sale')
    gray_image=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    return gray_image


def canny(img,low_threshold,high_threshold):
    """Applies the Canny Transform"""
    return  cv2.Canny(img,low_threshold,high_threshold)

# gray scale it
greyscaled_image = grayscale(img)
plt.subplot(2, 2, 2)
plt.imshow(greyscaled_image)
#cv2.imshow('grey scale',greyscaled_image)

# smooth it a bit with Gaussian blur
kernal_size = 11
blur_gray = gaussian_blur(img, kernal_size)

plt.subplot(2, 2, 3)
plt.imshow(blur_gray)
#cv2.imshow('gaussian ',blur_gray)

#Canny image detection

edges_image=canny(blur_gray,50,150)

plt.subplot(2, 2, 4)
plt.imshow(edges_image)
plt.show()
#cv2.imshow('Canny image detection',edges_image)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()

And this is my code for using cv2.imshow:

#REad Image
import numpy as np
import cv2
import matplotlib.pyplot as plt

def read_image_and_print_dims(image_path):
    """Reads and returns image.
    Helper function to examine ow an image is represented"""

    #reading an image
    image=cv2.imread(image_path)
    #printing out some stats and plottin
    print('This image is ',type(image),' with dinmesions',image.shape)
    #plt.subplot(2,2,3)
    cv2.imshow('Original Image',image)
    return image

image_path='fall-leaves.png'

img=read_image_and_print_dims(image_path)
#Make a blurred/smoothed version
def gaussian_blur(img,kernel_size):

    """Applies a Gaussian Noise Kernel"""
    print ('Inside Gaussian')

    return cv2.GaussianBlur(img,(kernel_size,kernel_size),4)

#Gray Scale Image
def grayscale(img):
    """Applies the Grayscale transform
        This will return an image with only one color channel
        but NOTE: to see the returned image as grayscale
        you should call plimshow(gray, cmap='gray')"""
    print ('Inside gray sale')
    gray_image=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    return gray_image


def canny(img,low_threshold,high_threshold):
    """Applies the Canny Transform"""
    return  cv2.Canny(img,low_threshold,high_threshold)


# gray scale it
greyscaled_image = grayscale(img)
#plt.subplot(2, 2, 1)

cv2.imshow('grey scale',greyscaled_image)

# smooth it a bit with Gaussian blur
kernal_size = 11
blur_gray = gaussian_blur(img, kernal_size)

#plt.subplot(2, 2, 2)
cv2.imshow('gaussian ',blur_gray)

#Canny image detection

edges_image=canny(blur_gray,50,150)

cv2.imshow('Canny image detection',edges_image)

cv2.waitKey(0)
cv2.destroyAllWindows()

Different images are obtained using pyplot and cv2. Shouldn't the same image be obtained?

Community
  • 1
  • 1
Himal Acharya
  • 836
  • 4
  • 14
  • 24
  • Just add `plt.show()`. And I don't think you need the last two lines, they have no effect, because you're trying to display your images with pyplot, not with opencv. If you want to display it with opencv, you should use `cv2.imshow("Whatever", blur_gray)`. – Headcrab Jun 09 '17 at 03:18
  • It worked..Different image is obtained while using cv2.imshow and pyplot -plt.show. Shouldn't same image need to be obtained while using any approach for plot? – Himal Acharya Jun 09 '17 at 04:01
  • When you use `cv2.imshow`, you immediately display one image, the one you passed to it as a parameter. When you use `plt.imshow`, you add an image to the plot, then later you can display the entire plot with `plt.show` - it shows all the images you've added there so far. Also pyplot may add some coordinate axis, legends etc., you can turn that on/off or tweak. – Headcrab Jun 09 '17 at 04:08
  • My question was why different image obatined forsame operations using pyplot and cv2. I have edited the question at end with figure. – Himal Acharya Jun 09 '17 at 04:24
  • @HimalAcharya please refrain from editing your question to ask a different question. Either try to work on it a little bit or open a new question if it deserves one. These are separate issues. – alkasm Jun 09 '17 at 04:59
  • 1
    @HimalAcharya That's probably because OpenCV uses BGR by default, while PyPlot uses RGB. – Headcrab Jun 09 '17 at 05:23

1 Answers1

3

You should use plt.show() to get the plot to display after you create the subplots.

Matplotlib assumes RGB order while OpenCV uses BGR ordering. To get the Matplotlib images the correct color, you need to swap the first and last channel around. You can use the built-in OpenCV method rgb_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB) to change them before you display them.

Also the images on the right in plt.imshow() are not using a gray colormap even though they are gray images. You need to use plt.imshow(blur_gray, cmap='gray') and plt.imshow(edges_image, cmap='gray') to use the grayscale colormap. cv2.imshow() always displays grayscale when there is only one channel. Your top set of code use the correct colormaps.

alkasm
  • 22,094
  • 5
  • 78
  • 94