Python matrix convolution without using numpy.convolve or scipy equivalent functions - python

I need to write a matrix convolution without using any built in functions to help. I am taking an image and turning it to greyscale, and then I'm supposed to pass a filter matrix over it. One of the filter matrices I have to use is:
[[-1,0,1],
[-1,0,1],
[-1,0,1]]
I understand how convolutions work, I just don't understand how to apply the convolution with code. Here is the code I am using to get my greyscale array:
import numpy
from scipy import misc
mylist = []
for i in myfile:
mylist.append(i)
for i in mylist:
q = i
print(q)
image = misc.imread(q[0:-1])
threshold()
image = misc.imread('image1.png')
def averageArr(pixel): #make the pixel color values more realistic
return 0.299*pixel[:,:,0] + 0.587*pixel[:,:,1] + 0.114*pixel[:,:,2]
def threshold():
picture = averageArr(image)
for i in range(0,picture.shape[0]): #begin thresholding
for j in range(0,picture.shape[1]):
myList.append(i,j)
misc.imsave('image1.png') #save the image file
I take the values from the function, and add them to a list, and then I am supposed to iterate over the list, but I'm not sure how to go about doing that. I can use scipy and numpy to read and arrange the matrix, but the actual convolution function has to be written.

Related

Luminance Correction (Prospective Correction)

When I was searching internet for an algorithm to correct luminance I came across this article about prospective correction and retrospective correction. I'm mostly interested in the prospective correction. Basically we take pictures of the scene with image in it(original one), and two other ,one bright and one dark, pictures where we only see the background of the original picture.
My problem is that I couldn't find any adaptation of these formulas in openCV or code example. I tried to use the formulas as they were in my code but this time I had a problem with data types. This happened when I tried to find C constant by applying operations on images.
This is how I implemented the formula in my code:
def calculate_C(im, im_b):
fx_mean = cv.mean(im)
fx_over_bx = np.divide(im,im_b)
mean_fx_bx = cv.mean(fx_over_bx)
c = np.divide(fx_mean, mean_fx_bx)
return c
#Basic image reading and resizing
# Original image
img = cv.imread(image_path)
img = cv.resize(img, (1000,750))
# Bright image
b_img = cv.imread(bright_image_path)
b_img = cv.resize(b_img, (1000,750))
# Calculating C constant from the formula
c_constant = calculate_C(img, b_img)
# Because I have only the bright image I am using second formula from the article
img = np.multiply(np.divide(img,b_img), c_constant)
When I try to run this code I get the error:
img = np.multiply(np.divide(img,b_img), c_constant)
ValueError: operands could not be broadcast together with shapes (750,1000,3) (4,)
So, is there anything I can do to fix my code? or is there any hints that you can share with me to handle luminance correction with this method or better methods?
You are using cv2.mean function which returns array with shape (4,) - mean value for each channel. You may need to ignore last channel and correctly broadcast it to numpy.
Or you could use numpy for calculations instead of opencv.
I just take example images from provided article.
grain.png:
grain_background.png:
Complete example:
import cv2
import numpy as np
from numpy.ma import divide, mean
f = cv2.imread("grain.png")
b = cv2.imread("grain_background.png")
f = f.astype(np.float32)
b = b.astype(np.float32)
C = mean(f) / divide(f, b).mean()
g = divide(f, b) * C
g = g.astype(np.uint8)
cv2.imwrite("grain_out.png", g)
Your need to use masked divide operation because ordinary operation could lead to division by zero => nan values.
Resulting image (output.png):

OpenCV warpAffine always return 0 matrix

I am using python opencv version 4.5.
import cv2
import numpy as np
rigidRect = np.float32([[50,-50],[50,50],[-50,50]])
shiftRect = np.float32([[50,-30],[50,70],[-50,70]])
M = cv2.getAffineTransform(rigidRect, shiftRect) #this return [[1,0,0],[0,1,20]]
validateRect = cv2.warpAffine(rigidRect, M, (2,3))
and validateRect return a 3 by 2 zeroes matrix.
I thought validateRect will equal to shiftRect?
warpAffine is used to transform an image using the affine transform matrix. What you are trying to do is to transform the given points, which is achieved by the transform function. Documentation of getAffineTransform gives hint about related functions in see also part.
validateRect = cv2.transform(rigidRect[None,:,:], M)

Sort Matrices by Mean Value Obtained

I'm working with OpenCV and Python.
I separated the green, red and blue components of an RGB image with OpenCV and Python. Then subdivide each of these matrices into 8x8 submatrices in order to work with them. So far, this is already done.
For each of the 8x8 submatrices that it generates, I need to obtain the mean of each one, and order the matrices in descending order according to the mean obtained. I'm stuck in this. I need help.
The code that I have so far is the following
import cv2
import numpy as np
img = cv2.imread("6.jpg")
b,g,r = cv2.split(img)
def sub_matrices(color_channel):
matrices = []
for i in range(int(color_channel.shape[0]/8)):
for j in range(int(color_channel.shape[1]/8)):
matrices.append(color_channel[i*8:i*8 + 8, j*8:j*8+8])
return matrices
#returns list of sub matrices
r_submatrices = sub_matrices(r)
g_submatrices = sub_matrices(g)
b_submatrices = sub_matrices(b)
print (r_submatrices)
print (g_submatrices)
print (b_submatrices)
for i in r_submatrices:
x = np.mean(i)
print(i)
I am using numpy to get the mean, but then I do not understand very well how I can order these matrices, depending on the value I get in the mean?
The easiest way is to calculate all the means, save the means and matrixes as pairs (you can use a tuple for this) and then sort.
matrix_mean_list = []
for i in r_submatrices:
x = np.mean(i)
matrix_mean_list.append((i, x))
matrix_mean_list = sorted(matrix_mean_list, key=lambda m: m[1])
Now matrix_mean_list should be sorted with respect to the means. You can iterate through it to get the matrixes back.

Save 3D array into a stack of 2D images in Python

I made a 3D array, which consists of numbers(0~4). What I want is to save 3D array as a stack of 2D images(if possible, save *.tiff file). What am I supposed to do?
import numpy as np
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
Actually, I made it. This is my code.
With this code, I don't need to stack a series of 2D image(array).
Make a 3D array, and save it. That is just what I did for this.
import numpy as np
from skimage.external import tifffile as tif
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
tif.imsave('a.tif', a, bigtiff=True)
This should work. I haven't tested it but I have separated color images into RGB slices using this method and it should work pretty much the same way here, assuming you don't want to do anything with those pixel values first. (They will be very close to the same color in an image).
import imageio
import numpy as np
a = np.random.randint(0,5, size=(100,100,100))
a = a.astype('int8')
for i in range(100):
newimage = a[:, :, i]
imageio.imwrite("path/to/image%d.tiff" %i, newimage)
What exactly do you mean by "stack"? As you refer to tiff as output format, I assume here you want your data in one file as a multiframe-tiff.
This can easily be done with imageio's mimwrite() function:
# import numpy as np
# a = np.random.randint(0,5, size=(100,100,100))
# a = a.astype('int8')
import imageio
imageio.mimwrite("image.tiff", a)
Note that this function relies on having the counter for your several frames as first parameter and x and y follw. See also its documentation.
However, if I'm wrong and you want to have n (e.g. 100) separate tif-files, you can also use the normal imwrite() function in a loop:
n = len(a)
for i in range(n):
imageio.imwrite(f'image_{i:03}.tiff', a[i])

Optimize iteration throught numpy array

I'm swapping values of a multidimensional numpy array in Python. But the code is too slow. Another thread says:
Typically, you avoid iterating through them directly. ... there's a good chance that it's easy to vectorize.
So, do you know a way to optimize the following code?
import PIL.Image
import numpy
pil_image = PIL.Image.open('Image.jpg').convert('RGB')
cv_image = numpy.array(pil_image)
# Convert RGB to BGR
for y in range(len(cv_image)):
for x in range(len(cv_image[y])):
(cv_image[y][x][0], cv_image[y][x][2]) = (cv_image[y][x][2],
cv_image[y][x][0])
For an 509x359 image this last more than one second, which is way too much. It should perform it's task in no time.
How about this single operation inverting the matrix along the last axis?
cv_image = cv_image[:,:,::-1]

Categories

Resources