How to embolden white areas in a MatPlotLib image? - python

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'))

Related

Blur the edges of image in Python

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?

OpenCV Contour Detection in color

I'm trying to detect the optic disc in an image of the back of the eye using OpenCV and findContour, then fitEllipse, but my program isn't detecting the optic disc at all. How do I fix this? Code and images are below
import cv2
import numpy as np
from sklearn.linear_model import LinearRegression
import math
from decimal import Decimal
def find_elongation(image):
img = cv2.imread(image,0)
ret,thresh = cv2.threshold(img,127,255,0)
contour,hierarchy = cv2.findContours(thresh, 1, 2)
contours = []
for i in range(len(contour)):
if len(contour[i])>=5:
contours.append(contour[i])
cnt = contours[0]
k = cv2.isContourConvex(cnt)
ellipse = cv2.fitEllipse(cnt)
im = cv2.ellipse(img,ellipse,(0,255,0),2)
(x,y),(ma,Ma),angle = cv2.fitEllipse(cnt)
return Ma/ma
print(find_elongation('eye.png'))
print(find_elongation('eye2.png'))
print(find_elongation('eye3.png'))
Image (one of them):
I'm trying to get the brightly colored circle in the middle:
Thanks for the help!
I have developed a piece of code to implement what you have asked. It mainly uses de Value channel of the HSV color space followed by some morphological operations.
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Read the image
img = cv2.imread('so.png')
# Transform the image to HSV color-space and keep only the value channel
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)
# Threshold the iamge with the 95% of the brightest possible pixels
maxVal = np.max(v)
per = 0.95
_, th = cv2.threshold(v, maxVal*per, 255, cv2.THRESH_BINARY)
# Erode the image and find the connected components
th = cv2.erode(th, np.ones((2,2), np.uint8))
n, conComp, stats, centroids = cv2.connectedComponentsWithStats(th)
# Obtain the sizes of the connectedComponents skipping the background
sizes = stats[1:,-1]
# Obtain the number of the connectedComponent with biggest size
nComp = np.argmax(sizes) + 1
# Isolate the connectedComponent and apply closing
out = np.zeros((img.shape[0], img.shape[1]), np.uint8)
out[conComp==nComp] = 1
out = cv2.morphologyEx(out, cv2.MORPH_CLOSE, np.ones((10,10)))
# Apply gradient to mask to obtain the border of the ellipse
out = cv2.morphologyEx(out, cv2.MORPH_GRADIENT, np.ones((2,2)))
# Join the border of the ellipse with the image to display it
img[out==1] = (0,0,0)
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.show()
I attach the output I have obtained with the picture you posted:

python opencv how to change hue in HSV channels

how to achieve img_update(hue_offset) function by changing the values of the hue channel by a dynamic hue_offset. To implement img_update(hue_offset) function, to achieve this Submission:
1.Change the values of the hue channel by a dynamic hue_offset.
import numpy as np
import cv2
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
def showImage(img, show_window_now = True):
# TODO: Convert the channel order of an image from BGR to RGB
#
# img = str(img)
img2 = cv2.imread(img)
img = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)
plt_img = plt.imshow(img)
if show_window_now:
plt.show()
return plt_img
# Prepare to show the original image and keep a reference so that we can update the image plot later.
plt.figure(figsize=(4, 6))
img = "hummingbird_from_pixabay.png"
plt_img = showImage(img, False)
# TODO: Convert the original image to HSV color space.
#
img_hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
def img_update(hue_offset):
print("Set hue offset to " + str(hue_offset))
# TODO: Change the hue channel of the HSV image by `hue_offset`.
# Mind that hue values in OpenCV range from 0-179.
# ???
# TODO: Convert the modified HSV image back to RGB
# and update the image in the plot window using `plt_img.set_data(img_rgb)`.
#
# ???
#
# Create an interactive slider for the hue value offset.
ax_hue = plt.axes([0.1, 0.04, 0.8, 0.06]) # x, y, width, height
slider_hue = Slider(ax=ax_hue, label='Hue', valmin=0, valmax=180, valinit=0, valstep=1)
slider_hue.on_changed(img_update)
# Now actually show the plot window
plt.show()
This is one way to do that in Python/OpenCV.
Input:
import cv2
import numpy as np
# read image
img = cv2.imread("bird.png")
# convert img to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h = hsv[:,:,0]
s = hsv[:,:,1]
v = hsv[:,:,2]
# shift the hue
# cv2 will clip automatically to avoid color wrap-around
huechange = 85 # 0 is no change; 0<=huechange<=180
hnew = cv2.add(h, huechange)
# combine new hue with s and v
hsvnew = cv2.merge([hnew,s,v])
# convert from HSV to BGR
result = cv2.cvtColor(hsvnew, cv2.COLOR_HSV2BGR)
# save result
cv2.imwrite('bird_hue_changed.png', result)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result for hue shifted by 85:

Finding only the red pixel in a image and darkening it to more red

I want to find only the red pixel in a image and darkening it to more red, currently i have this basic code, Is there any better way to get very good results, Please do suggest. Thank You
import cv2
import numpy as np
img = cv2.imread('2.jpg', 1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
import matplotlib.pyplot as plt
plt.imshow(img)
plt.show()
img = cv2.addWeighted(img, 0.9, np.zeros(img.shape, img.dtype), 0, 0)
rows,cols, val = img.shape
for i in range(rows):
for j in range(cols):
k = img[i,j]
#print(k)
if(k[0] < 255):
k[0] = 255
print(k)
contrast_img = cv2.addWeighted(img, 0.8, np.zeros(img.shape, img.dtype), 0, 0)
plt.imshow(contrast_img)
Input
Expected output
Here is one way to increase the contrast of the red (and all colors) using Python/OpenCV/Skimage. Adjust the factor of min in the skimage.exposure function.
Input:
import cv2
import numpy as np
import skimage.exposure
# read image
img = cv2.imread('red_text.jpg')
# get min and max values
min = np.amin(img)
max = np.amax(img)
print("min=",min, "max=",max)
# increase contrast
result = skimage.exposure.rescale_intensity(img, in_range=(2*min,max), out_range=(0,255))
# save output image
cv2.imwrite('red_text_enhanced.jpg', result)
# display IN and OUT images
cv2.imshow('RESULT', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Image standardisation and normalisation using Numpy and OpenCV

I am trying to standardize and then normalise an image using Numpy and OpenCV in the following manner; however, the image that's output from matplotlib looks identical. Why is that?
Code
%matplotlib inline
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
IMG_SIZE = 256
def show_img(img):
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
imgplot = plt.imshow(img_rgb)
img = cv2.imread('/content/drive/My Drive/ai/test_images/test_image3.tif')
img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))
show_img(img)
img = img.astype('float32')
img = (img - img.mean(axis=(0, 1, 2), keepdims=True)) / img.std(axis=(0, 1, 2), keepdims=True)
img = cv2.normalize(img, None, 0, 1, cv2.NORM_MINMAX)
show_img(img)
It is a normal behaviour. Normalizing an image means to change its ranges from 0-255 to 0-1. Matplotlib checks the range of the RGB values and display the image accordingly.
As for standardisation, if you look closely you can see a color shift. Orange seems a little lighter on the second image.
These behaviours are normal because preprocessing should not change the image (at least the information inside) but should help the model to processed them ALL.

Categories