I am trying to remove random pixel clusters noise from a transparent png using python.
I have used eroding and then dilating like this
import cv2
import numpy as np
img = cv2.imread('test1.png')
blurred_img = cv2.medianBlur(img, 1)
kernel = np.ones((2,2),np.uint8)
erosion = cv2.erode(blurred_img, kernel, iterations=1)
output = cv2.dilate(erosion, kernel, iterations=1)
cv2.imwrite('output.png', output)
but this blurs the image to the point where it loses a lot of details:
I have tried many alternatives but I just can't obtain the result I want... The original image just without that random pixel noise around it. I hope someone can help me.
area_opening from skimage can be used on the alpha channel. We use the cv2.IMREAD_UNCHANGED flag to get this channel and modify it.
the following code has an output
import cv2
import numpy as np
from skimage.morphology import area_opening
img = cv2.imread('test.png', cv2.IMREAD_UNCHANGED)
img[:,:,3][area_opening(img[:,:,3], 7) == 0] = 0
cv2.imwrite('output.png', img)
I'm trying to read a binary RGB image and blur just the edges. This is my non-working code upto now. I get this error: "ValueError: operands could not be broadcast together with shapes (2048,2048,3) (2048,2048)"
import cv2
import numpy as np
import skimage.exposure
import matplotlib.pyplot as plt
# load image
img = cv2.imread('mask.png')
# Get edges
edges = cv2.Canny(image=img.astype(np.uint8), threshold1=100, threshold2=200) # Canny Edge Detection
#Remove edges from image
img = img - edges
# Blur
blur = cv2.GaussianBlur(edges, (0,0), sigmaX=2.5, sigmaY=2.5, borderType = cv2.BORDER_DEFAULT)
img = img + blur
# save output
cv2.imwrite('bw_image_antialiased.png', img)
Is there a better way to do this? Faster, more efficient?
I want to create a blank image and first try converting a ndarray to PIL Image, however, generating the wrong image. Why does this strange thing happen?
from PIL import Image
import numpy as np
x = np.ones((256, 256)).astype(bool)
img = Image.new('1', (256, 256), 1)
y = np.asarray(img)
print((x == y).all())
# x equals to y, but ploting different pictures, why?
img1 = Image.fromarray(x, mode='1')
img1.show()
img2 = Image.fromarray(y, mode='1')
img2.show()
Change the mode to 8 bit pixels not only in Image.new but also in Image.fromarray:
from PIL import Image
import numpy as np
x = np.ones((256, 256)).astype(bool)
img = Image.new('L', (256, 256), 1)
y = np.asarray(img)
img1 = Image.fromarray(x, mode='L')
img1.show()
img2 = Image.fromarray(y, mode='L')
img2.show()
I have read in an picture of a word in Python using MatPlotLib, inverted it and would like to make all white areas larger to embolden the word. How could I do this?
My assumption is that I would need to look at all pixels within a range r of the white pixels and color them white as well. Is this correct?
Please find the code, the example and the desired result below. The dimensions of the image are (465, 748), and
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import pandas as pd
# Code to transform RGB-image into GrayScale and subsequently into inverted BW image.
def rgb2gray(rgb):
# Convert RGB to GrayScale
gray_value = np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
# Invert GrayScale.
gray_value = 1 - gray_value
# Apply a threshold.
gray_value[gray_value >= 0.5] = 1
gray_value[gray_value < 0.5] = 0
return gray_value
# Read in image.
img = mpimg.imread('Data/Development/Image_Test.png')
# BW-scale.
gray = rgb2gray(img)
# Show image.
plt.imshow(gray, cmap = plt.get_cmap('gray'))
The source image:
The desired result:
The solution is to let the white areas dilate. In this solution I have taken r = 10 pixels, by letting the dilation run for 10 iterations.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import pandas as pd
# Code to transform RGB-image into GrayScale and subsequently into inverted BW image.
def rgb2gray(rgb):
# Convert RGB to GrayScale
gray_value = np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
# Invert GrayScale.
gray_value = 1 - gray_value
# Apply a threshold.
gray_value[gray_value >= 0.5] = 1
gray_value[gray_value < 0.5] = 0
return gray_value
# Read in image.
img = mpimg.imread('Data/Development/Image_Test.png')
# BW-scale.
gray = rgb2gray(img)
# Dilate the white areas.
gray = ndimage.binary_dilation( gray, iterations = 10 ).astype( gray.dtype )
# Show image.
plt.imshow(gray, cmap = plt.get_cmap('gray'))
This question already has answers here:
OpenCV giving wrong color to colored images on loading
(7 answers)
Closed 5 years ago.
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?
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.