I know that I can rotate images in tensorflow using tf.contrib.image.rotate. But suppose I want to apply the rotation randomly at an angle between -0.3 and 0.3 in radians as follows:
images = tf.contrib.image.rotate(images, tf.random_uniform(shape=[batch_size], minval=-0.3, maxval=0.3, seed=mseed), interpolation='BILINEAR')
So far this will work fine. But the problem arises when the batch size changes on the last iteration and I got an error. So how to fix this code and make it work in all case scenarios? Please note that the inputs images are fed using tf.data.Dataset api.
Any help is much appreciated!!
You can't feed tf.contrib.image.rotate with an angles tensor.
But if you inspect the source code you can see it just makes a bunch of argument validations, and then:
image_height = math_ops.cast(array_ops.shape(images)[1],
dtypes.float32)[None]
image_width = math_ops.cast(array_ops.shape(images)[2],
dtypes.float32)[None]
output = transform(
images,
angles_to_projective_transforms(angles, image_height, image_width),
interpolation=interpolation)
tf.contrib.image.transform() receives a projective transform matrix.
tf.contrib.image.angles_to_projective_transforms() generates projective transforms from the rotation angles.
Both accept tensors as arguments, so you can just call the underlying functions.
Here is an example using MNIST
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# load mnist
from tensorflow.examples.tutorials.mnist
import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot = True)
# Tensorflow random angle rotation
input_size = mnist.train.images.shape[1]
side_size = int(np.sqrt(input_size))
dataset = tf.placeholder(tf.float32, [None, input_size])
images = tf.reshape(dataset, (-1, side_size, side_size, 1))
random_angles = tf.random.uniform(shape = (tf.shape(images)[0], ), minval = -np
.pi / 4, maxval = np.pi / 4)
rotated_images = tf.contrib.image.transform(
images,
tf.contrib.image.angles_to_projective_transforms(
random_angles, tf.cast(tf.shape(images)[1], tf.float32), tf.cast(tf
.shape(images)[2], tf.float32)
))
# Run and Print
sess = tf.Session()
result = sess.run(rotated_images, feed_dict = {
dataset: mnist.train.images,
})
original = np.reshape(mnist.train.images * 255, (-1, side_size, side_size)).astype(
np.uint8)
rotated = np.reshape(result * 255, (-1, side_size, side_size)).astype(np.uint8)
# Print 10 random samples
fig, axes = plt.subplots(2, 10, figsize = (15, 4.5))
choice = np.random.choice(range(len(mnist.test.labels)), 10)
for k in range(10):
axes[0][k].set_axis_off()
axes[0][k].imshow(original[choice[k, ]], interpolation = 'nearest', \
cmap = 'gray')
axes[1][k].set_axis_off()
axes[1][k].imshow(rotated[choice[k, ]], interpolation = 'nearest', \
cmap = 'gray')
Related
I am trying to feed a very large image into Triton server. I need to divide the input image into patches and feed the patches one by one into a tensorflow model. The image has a variable size, so the number of patches N is variable for each call.
I think a Triton ensemble model that calls the following steps would do the job:
A python model (pre-process) to create the patches
The segmentation model
Finally another python model (post-process) to merge the output patches into a big output mask
However, for this, I would have to write a config. pbtxt file with 1:N and N:1 relation, meaning the ensemble scheduler needs to call the 2nd step multiple times and the 3rd once with the aggregated output.
Is this possible, or do I need to use some other technique?
Disclaimer
The below answer isn't the actual solution to the above question. I misunderstood the above query. But I'm leaving this response in case of future readers find it useful.
Input
import cv2
import matplotlib.pyplot as plt
input_img = cv2.imread('/content/2.jpeg')
print(input_img.shape) # (719, 640, 3)
plt.imshow(input_img)
Slice and Stitch
The following functionality is adopted from here. More details and discussion can be found here.. Apart from the original code, we bring together the necessary functionality and put them in a single class (ImageSliceRejoin).
# ref: https://github.com/idealo/image-super-resolution
class ImageSliceRejoin:
def pad_patch(self, image_patch, padding_size, channel_last=True):
""" Pads image_patch with padding_size edge values. """
if channel_last:
return np.pad(
image_patch,
((padding_size, padding_size),
(padding_size, padding_size), (0, 0)),
'edge',
)
else:
return np.pad(
image_patch,
((0, 0), (padding_size, padding_size), (padding_size, padding_size)),
'edge',
)
# function to split the image into patches
def split_image_into_overlapping_patches(self, image_array, patch_size, padding_size=2):
""" Splits the image into partially overlapping patches.
The patches overlap by padding_size pixels.
Pads the image twice:
- first to have a size multiple of the patch size,
- then to have equal padding at the borders.
Args:
image_array: numpy array of the input image.
patch_size: size of the patches from the original image (without padding).
padding_size: size of the overlapping area.
"""
xmax, ymax, _ = image_array.shape
x_remainder = xmax % patch_size
y_remainder = ymax % patch_size
# modulo here is to avoid extending of patch_size instead of 0
x_extend = (patch_size - x_remainder) % patch_size
y_extend = (patch_size - y_remainder) % patch_size
# make sure the image is divisible into regular patches
extended_image = np.pad(image_array, ((0, x_extend), (0, y_extend), (0, 0)), 'edge')
# add padding around the image to simplify computations
padded_image = self.pad_patch(extended_image, padding_size, channel_last=True)
xmax, ymax, _ = padded_image.shape
patches = []
x_lefts = range(padding_size, xmax - padding_size, patch_size)
y_tops = range(padding_size, ymax - padding_size, patch_size)
for x in x_lefts:
for y in y_tops:
x_left = x - padding_size
y_top = y - padding_size
x_right = x + patch_size + padding_size
y_bottom = y + patch_size + padding_size
patch = padded_image[x_left:x_right, y_top:y_bottom, :]
patches.append(patch)
return np.array(patches), padded_image.shape
# joing the patches
def stich_together(self, patches, padded_image_shape, target_shape, padding_size=4):
""" Reconstruct the image from overlapping patches.
After scaling, shapes and padding should be scaled too.
Args:
patches: patches obtained with split_image_into_overlapping_patches
padded_image_shape: shape of the padded image contructed in split_image_into_overlapping_patches
target_shape: shape of the final image
padding_size: size of the overlapping area.
"""
xmax, ymax, _ = padded_image_shape
# unpad patches
patches = patches[:, padding_size:-padding_size, padding_size:-padding_size, :]
patch_size = patches.shape[1]
n_patches_per_row = ymax // patch_size
complete_image = np.zeros((xmax, ymax, 3))
row = -1
col = 0
for i in range(len(patches)):
if i % n_patches_per_row == 0:
row += 1
col = 0
complete_image[
row * patch_size: (row + 1) * patch_size, col * patch_size: (col + 1) * patch_size, :
] = patches[i]
col += 1
return complete_image[0: target_shape[0], 0: target_shape[1], :]
Initiate Slicing
import numpy as np
isr = ImageSliceRejoin()
padding_size = 1
patches, p_shape = isr.split_image_into_overlapping_patches(
input_img,
patch_size=220,
padding_size=padding_size
)
patches.shape, p_shape, input_img.shape
((12, 222, 222, 3), (882, 662, 3), (719, 640, 3))
Verify
n = np.ceil(patches.shape[0] / 2)
plt.figure(figsize=(20, 20))
patch_size = patches.shape[1]
for i in range(patches.shape[0]):
patch = patches[i]
ax = plt.subplot(n, n, i + 1)
patch_img = np.reshape(patch, (patch_size, patch_size, 3))
plt.imshow(patch_img.astype("uint8"))
plt.axis("off")
Inference
I'm using the Image-Super-Resolution model for demonstration.
# import model
from ISR.models import RDN
model = RDN(weights='psnr-small')
# number of patches that will pass to model for inference:
# here, batch_size < len(patches)
batch_size = 2
for i in range(0, len(patches), batch_size):
# get some patches
batch = patches[i: i + batch_size]
# pass them to model to give patches output
batch = model.model.predict(batch)
# save the output patches
if i == 0:
collect = batch
else:
collect = np.append(collect, batch, axis=0)
Now, the collect holds the output of each patch from the model.
patches.shape, collect.shape
((12, 222, 222, 3), (12, 444, 444, 3))
Rejoin Patches
scale = 2
padded_size_scaled = tuple(np.multiply(p_shape[0:2], scale)) + (3,)
scaled_image_shape = tuple(np.multiply(input_img.shape[0:2], scale)) + (3,)
sr_img = isr.stich_together(
collect,
padded_image_shape=padded_size_scaled,
target_shape=scaled_image_shape,
padding_size=padding_size * scale,
)
Verify
print(input_img.shape, sr_img.shape)
# (719, 640, 3) (1438, 1280, 3)
fig, ax = plt.subplots(1,2)
fig.set_size_inches(18.5, 10.5)
ax[0].imshow(input_img)
ax[1].imshow(sr_img.astype('uint8'))
I have a simple sum pooling implemented in keras tensorflow, using AveragePooling2D*N*N, so it creates a sum of the elements in pool with some shape, same padding so the shape won't change:
import numpy as np
import seaborn as sns
import matplotlib.pylab as plt
import tensorflow as tf
from tensorflow.keras.backend import square
#generating the example matrix
def getMatrixByDefinitions(definitions, width, height):
matrix = np.zeros((width, height))
for definition in definitions:
x_cor = definition[1]
y_cor = definition[0]
value = definition[2]
matrix.itemset((x_cor, y_cor), value)
return matrix
generated = getMatrixByDefinitions(width=32, height=32, definitions =[[7,16,1]])
def avg_pool(pool):
return tf.keras.layers.AveragePooling2D(pool_size=(pool,pool), strides=(1, 1), padding='same')
def summer(pool, tensor):
return avg_pool(pool)(tensor)*pool*pool
def numpyToTensor(numpy_data):
numpy_as_array = np.asarray(numpy_data)
tensor_data = numpy_as_array.reshape(1, numpy_data.shape[1], numpy_data.shape[1], 1)
return tensor_data
data = numpyToTensor(generated)
pooled_data = summer(11, data)
def printMatrixesToHeatMap(matrixes, title):
# f = pyplot.figure() # width and height in inches
matrix_count = len(matrixes)
width_ratios = [4] * matrix_count + [0.2]
mergedMatrixes = matrixes[0][0]
for matrix in matrixes:
mergedMatrixes = np.concatenate((mergedMatrixes, matrix[0]), axis=0)
vmin = np.min(mergedMatrixes)
vmax = np.max(mergedMatrixes)
fig, axs = plt.subplots(ncols=matrix_count + 1, gridspec_kw=dict(width_ratios=width_ratios))
fig.set_figheight(20)
fig.set_figwidth(20 * matrix_count + 5)
axis_id = 0
for matrix in matrixes:
sns.heatmap(matrix[0], annot=True, cbar=False, ax=axs[axis_id], vmin=vmin, vmax=vmax)
axs[axis_id].set_title(matrix[1])
axis_id = axis_id + 1
#fig.colorbar(axs[1].collections[0], cax=axs[matrix_count])
fig.savefig(title+".pdf", bbox_inches='tight')
def tensorToNumpy(tensor):
width = tensor.get_shape()[1]
height = tensor.get_shape()[2]
output = tf.reshape(tensor, [width, height])
#output = output.eval(session=tf.compat.v1.Session())
output = output.numpy()
return np.array(output)
printMatrixesToHeatMap([[tensorToNumpy(pooled_data), "Pooled data"]],
"name")
After testing it on very simple 2D array I have found out it does not do what I expect (original and pooled data):
You can see that the single one sum-pooled (according to average pooling) ended up with sum greater than real sum, which is 1, near the borders. (in this case max can be used, but the real data are more complex and we need sum) This would mean that average near borders is count not from padded data but the original. Or is this misunderstanding of padding from my side? I need to have ones on indices where 1.1, 1.2, 1.4 is. Why is this and how can I solve such problem?
Note that I do not want to manually set the correct sum, so I am looking for a way to achieve this in keras pooling itself.
It seems to be a problem with the "SAME" padding algorithm. Unfortunately,there is no way of specifying an explicit padding to the avg_pool2d op. It is possible to manually pad the input with tf.pad though. Here is a really naive approach to padding that will work with odd shaped pooling filters and strides size of 1 :
generated = getMatrixByDefinitions(width=32, height=32, definitions =[[7,16,1]])
gen_nhwc = tf.constant(generated[np.newaxis,:,:,np.newaxis])
pool = 11
paddings = [[0,0],[pool//2,pool//2],[pool//2,pool//2],[0,0]]
gen_pad = tf.pad(gen_nhwc, paddings, "CONSTANT")
res = tf.nn.avg_pool2d(gen_pad, (pool,pool), (1,1),"VALID")*pool*pool
result = np.squeeze(res.numpy())
printMatrixesToHeatMap([[generated, "input"],[result, "output"]], "name")
Results in images :
Edit : I created an issue on Github regarding the problem.
I have a RGB image. I want to apply PCA for image-compression and see the output after the application.
Here's what I tried to do:
from PIL import Image
import numpy as np
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
------
def load_image(infilename):
img = Image.open(infilename)
img.load()
img.show()
data = np.asarray(img, dtype="int32")
return data
---------
data = load_image("Image_for_pca.jpg")
r = data[:,:,0]
print("r", r.shape)
g = data[:,:,1]
print("g", g.shape)
b = data[:,:,2]
print("b", b.shape)
concat_matrix_image = np.hstack((np.hstack((r,g)),b))
print("concatMatrixImage", concat_matrix_image.shape)
output of the prints:
r (161, 212)
g (161, 212)
b (161, 212)
concatMatrixImage (161, 636)
# list of dimension
pca_number_of_wanted_dimension = [3 ,5 ,10 ,15 ,20 ,30]
-------
def create_pca_model(number_of_components):
pca = PCA(n_components=number_of_components)
return pca
-------
def plot_varience_on_pca(pca):
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.title("The number of wanted dimension is {}".format(pca.n_components))
plt.xlabel('number of components')
plt.ylabel('cumulative explained variance')
plt.show()
------
def recover_pic(pca, principal_components):
#Project lower dimension data onto original features
approximation = pca.inverse_transform(principal_components)
approximation = approximation.reshape(-1,161,212)
# approximation = approximation.astype(np.uint8)
# print(approximation.shape)
# img = Image.fromarray(approximation, 'RGB')
approximation.show()
-------
for i in pca_number_of_wanted_dimension:
pca = create_pca_model(i)
principal_components = pca.fit_transform(concat_matrix_image)
print(principal_components.shape)
recover_pic(pca, principal_components)
plot_varience_on_pca(pca)
How to recover the picture after the pca.inverse_transform?
Since I don't have your data, I have to show you how you can do using my data.
Loading data and displaying data
from sklearn.datasets import fetch_olivetti_faces
from sklearn.model_selection import train_test_split
from matplotlib.pyplot import subplots
from matplotlib.pyplot import suptitle
from matplotlib.pyplot import savefig
from sklearn.decomposition import PCA
def display_set(n_row, n_col, x, y_, t, title="Id:{}",
fig_size=(6, 3), dpi_=300, f_name="default.png"):
fig, ax = subplots(n_row, n_col, figsize=fig_size, dpi=dpi_)
ax = ax.flatten()
for i in range(n_row * n_col):
ax[i].imshow(X=x[i], cmap='gray')
ax[i].set_xticks([])
ax[i].set_yticks([])
ax[i].set_title(title.format(y_[i]))
suptitle(t=t)
savefig(f_name)
olivetti = fetch_olivetti_faces()
X = olivetti.images # Train
y = olivetti.target # Labels
x_train, x_test, y_train, y_test = train_test_split(X, y,
test_size=0.3,
random_state=42)
train_name = "train_samples.png"
test_name = "test_samples.png"
display_set(n_row=2, n_col=10, x=x_train, y_=y_train,
t="Train-set samples", title="Id:{}", f_name=train_name)
display_set(n_row=2, n_col=10, x=x_test, y_=y_test,
t="Test-set samples", title="Id:{}", f_name=test_name)
The output of train samples:
The output of test samples:
Now lets create a pca object
x_train = x_train.reshape((x_train.shape[0], X.shape[1] * X.shape[2]))
x_test = x_test.reshape((x_test.shape[0], X.shape[1] * X.shape[2]))
pca_train = PCA(n_components=100).fit(X=x_train)
pca_test = PCA(n_components=100).fit(X=x_test)
eig_num_tr = len(pca_train.components_)
eig_num_te = len(pca_test.components_)
# eigen training faces
eig_tr_faces = pca_train.components_.reshape((eig_num_tr, X.shape[1], X.shape[2]))
# eigen test faces
eig_te_faces = pca_test.components_.reshape((eig_num_te, X.shape[1], X.shape[2]))
title_tr = "PCA Applied Train-set samples"
title_te = "PCA Applied Test-set samples"
t_ = "Eig. Id:{}"
display_set(n_row=2, n_col=5, x=eig_tr_faces, y_=range(0, eig_num_tr-1),
t=title_tr, title=t_, fig_size=(6, 3.2))
display_set(n_row=2, n_col=5, x=eig_te_faces, y_=range(0, eig_num_te-1),
t=title_te, title=t_, fig_size=(6, 3.2))
The output of the training set:
The output of the test set:
In Tensorflow I am training from a set of PNG files and I wish to apply data augmentation. I have successfully used tf.image.random_flip_left_right()
But I get an error when I try to use tf.image.central_crop().
basically I would like the central_fraction to be drawn from a uniform distribution (0.8,1.0].
Here is my code. Where did I go wrong? Should frac be a tf.random_uniform()?
filename_queue = tf.train.string_input_producer( tf.train.match_filenames_once("./images/*.png"))
image_reader = tf.WholeFileReader() # Read an entire image file
_, image_file = image_reader.read(filename_queue)
image = tf.image.decode_png(image_file, channels=3, dtype=tf.uint8, name="PNGDecompressor")
image.set_shape([800,400,3])
frac = random.uniform(0.8,1.0)
image = tf.image.central_crop(image, central_fraction = frac) # THIS FAILS
# image = tf.image.central_crop(image, central_fraction = 0.8) # THIS WORKS
image = tf.image.resize_images(image, [256, 128])
image.set_shape([256,128,3])
image = tf.cast(image, tf.float32) * (1. / 255) - 0.5 # Convert from [0, 255] -> [-0.5, 0.5] floats.
image = tf.image.per_image_whitening(image)
image = tf.image.random_flip_left_right(image, seed=42)
# Start a new session to show example output.
with tf.Session() as sess:
tf.initialize_all_variables().run()
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
t_image= sess.run([image])
[...]
coord.request_stop()
coord.join(threads)
Fails with error:
TypeError: Fetch argument 0.9832154064713503 has invalid type <class 'float'>, must be a string or Tensor. (Can not convert a float into a Tensor or Operation.)
I solved my own problem defining the following function. I adjusted the code provided in tf.image.central_crop(image, central_fraction).
The function RandomCrop will crop an image taking a central_fraction drawn from a uniform distribution. You can just specify the min and max fraction you want.
You can replace random_uniform distribution to a different one obviously.
def RandomCrop(image,fMin, fMax):
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import array_ops
from tensorflow.python.framework import ops
image = ops.convert_to_tensor(image, name='image')
if fMin <= 0.0 or fMin > 1.0:
raise ValueError('fMin must be within (0, 1]')
if fMax <= 0.0 or fMax > 1.0:
raise ValueError('fMin must be within (0, 1]')
img_shape = array_ops.shape(image)
depth = image.get_shape()[2]
my_frac2 = tf.random_uniform([1], minval=fMin, maxval=fMax, dtype=tf.float32, seed=42, name="uniform_dist")
fraction_offset = tf.cast(math_ops.div(1.0 , math_ops.div(math_ops.sub(1.0,my_frac2[0]), 2.0)),tf.int32)
bbox_h_start = math_ops.div(img_shape[0], fraction_offset)
bbox_w_start = math_ops.div(img_shape[1], fraction_offset)
bbox_h_size = img_shape[0] - bbox_h_start * 2
bbox_w_size = img_shape[1] - bbox_w_start * 2
bbox_begin = array_ops.pack([bbox_h_start, bbox_w_start, 0])
bbox_size = array_ops.pack([bbox_h_size, bbox_w_size, -1])
image = array_ops.slice(image, bbox_begin, bbox_size)
# The first two dimensions are dynamic and unknown.
image.set_shape([None, None, depth])
return(image)
To better understand gabor filters and kernels in image processing, I am trying to place my own images into a Gabor texture comparison template from the scikit-image site.
The code modification I used was adding first line below and pointing second line to my new variable. Previous structured paralleled following line in code quoted below.
img=plt.imread('greenBalloon.png') #This is code I added to read in the local png file
brick = img_as_float(img)[shrink] #Using pre-existing line with my swapped variable
I continue to get errors when trying to swap out the included sample data file with another png present in the working directory. I get the following error:
"RuntimeError: filter weights array has incorrect shape."
How should I re-write this code to pull in a locally saved image or, preferably, set of images in place of the sample(s)?
from __future__ import print_function
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from scipy import ndimage as nd
from skimage import data
from skimage.util import img_as_float
from skimage.filter import gabor_kernel
def compute_feats(image, kernels):
feats = np.zeros((len(kernels), 2), dtype=np.double)
for k, kernel in enumerate(kernels):
filtered = nd.convolve(image, kernel, mode='wrap')
feats[k, 0] = filtered.mean()
feats[k, 1] = filtered.var()
return feats
def match(feats, ref_feats):
min_error = np.inf
min_i = None
for i in range(ref_feats.shape[0]):
error = np.sum((feats - ref_feats[i, :])**2)
if error < min_error:
min_error = error
min_i = i
return min_i
# prepare filter bank kernels
kernels = []
for theta in range(4):
theta = theta / 4. * np.pi
for sigma in (1, 3):
for frequency in (0.05, 0.25):
kernel = np.real(gabor_kernel(frequency, theta=theta,
sigma_x=sigma, sigma_y=sigma))
kernels.append(kernel)
shrink = (slice(0, None, 3), slice(0, None, 3))
img=plt.imread('greenBalloon.png') #This is code I added to read in the local png file
brick = img_as_float(img)[shrink] #Using pre-existing line with my swapped variable
grass = img_as_float(data.load('grass.png'))[shrink]
wall = img_as_float(data.load('rough-wall.png'))[shrink]
image_names = ('brick', 'grass', 'wall')
images = (brick, grass, wall)
# prepare reference features
ref_feats = np.zeros((3, len(kernels), 2), dtype=np.double)
ref_feats[0, :, :] = compute_feats(brick, kernels)
ref_feats[1, :, :] = compute_feats(grass, kernels)
ref_feats[2, :, :] = compute_feats(wall, kernels)
print('Rotated images matched against references using Gabor filter banks:')
print('original: brick, rotated: 30deg, match result: ', end='')
feats = compute_feats(nd.rotate(brick, angle=190, reshape=False), kernels)
print(image_names[match(feats, ref_feats)])
print('original: brick, rotated: 70deg, match result: ', end='')
feats = compute_feats(nd.rotate(brick, angle=70, reshape=False), kernels)
print(image_names[match(feats, ref_feats)])
print('original: grass, rotated: 145deg, match result: ', end='')
feats = compute_feats(nd.rotate(grass, angle=145, reshape=False), kernels)
print(image_names[match(feats, ref_feats)])
def power(image, kernel):
# Normalize images for better comparison.
image = (image - image.mean()) / image.std()
return np.sqrt(nd.convolve(image, np.real(kernel), mode='wrap')**2 +
nd.convolve(image, np.imag(kernel), mode='wrap')**2)
# Plot a selection of the filter bank kernels and their responses.
results = []
kernel_params = []
for theta in (0, 1):
theta = theta / 4. * np.pi
for frequency in (0.1, 0.4):
kernel = gabor_kernel(frequency, theta=theta)
params = 'theta=%d,\nfrequency=%.2f' % (theta * 180 / np.pi, frequency)
kernel_params.append(params)
# Save kernel and the power image for each image
results.append((kernel, [power(img, kernel) for img in images]))
fig, axes = plt.subplots(nrows=5, ncols=4, figsize=(5, 6))
plt.gray()
fig.suptitle('Image responses for Gabor filter kernels', fontsize=12)
axes[0][0].axis('off')
# Plot original images
for label, img, ax in zip(image_names, images, axes[0][1:]):
ax.imshow(img)
ax.set_title(label, fontsize=9)
ax.axis('off')
for label, (kernel, powers), ax_row in zip(kernel_params, results, axes[1:]):
# Plot Gabor kernel
ax = ax_row[0]
ax.imshow(np.real(kernel), interpolation='nearest')
ax.set_ylabel(label, fontsize=7)
ax.set_xticks([])
ax.set_yticks([])
# Plot Gabor responses with the contrast normalized for each filter
vmin = np.min(powers)
vmax = np.max(powers)
for patch, ax in zip(powers, ax_row[1:]):
ax.imshow(patch, vmin=vmin, vmax=vmax)
ax.axis('off')
plt.show()
Any other insights on processing images with gabor patches would be quite helpful.
just use a black&white version to run the algorithm.
To do it, just pass the argument 'as_grey' to imread.
image = skimage.io.imread(image_path,as_grey=True)