Trying to write a simple lowpass filter in python to run against lena. Then I'd like to run an inverse filter to run against the lowpass and try to get the original back (well, as close to original). I'm new to programming in python and not quite sure where to start.
I tried rearranging a highpass filter code but it doesn't look right.
import matplotlib.pyplot as plt
import numpy as np
import scipy.misc
from scipy import ndimage
import Image
#lowpass
def plot(data, title):
plot.i += 1
plt.subplot(2,2,plot.i)
plt.imshow(data)
plt.gray()
plt.title(title)
plot.i = 0
# Load the data...
img = scipy.misc.lena()
data = np.array(img, dtype=float)
plot(data, 'Original')
#narrow lowpass filter
kernel = np.array([[1, 1, 1],
[1, -8, 1],
[1, 1, 1]])
lp_3 = ndimage.convolve(data, kernel)
plot(lp_3, '3x3 Lowpass')
# A slightly "wider" lowpass filter
kernel = np.array([[1, 1, 1, 1, 1],
[1, -1, -2, -1, 1],
[1, -2, -4, -2, 1],
[1, -1, -2, -1, 1],
[1, 1, 1, 1, 1]])
lp_5 = ndimage.convolve(data, kernel)
plot(lp_5, '5x5 Lowpass')
plt.show()
You should definitely check your kernel first. It does not look like a lowpass (averaging) kernel at all. Try first something like
kernel = np.ones((n,n))
if you want to do a very simple lowpass filter n by n (i.e. blurring):
Related
I am trying to figure out how to do this with numpy, so I can then convert it to c++ from scratch. I have figured out how to do it when the mode is constant. The way that is done is shown below.
import numpy as np
from scipy import signal
a = np.array([[1, 2, 0, 0], [5, 3, 0, 4], [0, 0, 0, 7], [9, 3, 0, 0]])
k = np.array([[1,0,0],[0,1,0],[0,0,0]])
a = np.pad(a, 1)
k = np.flip(k)
output = signal.convolve(a, k, 'valid')
Which then comes out to the same output as scipy.ndimage.filters.convolve(a, k, mode='constant) So I thought that when the mode was reflect it would work the same way. Except, that the line a = np.pad(a, 1) would be changed to a = np.pad(a, 1, mode='reflect'). However, that does not seem to be the case. Could someone explain how it would work from scratch using numpy and scipy.signal.convolve? Thank you.
import numpy as np
import sympy as sp
Vec = np.matrix([[1,1,1,5],[1,2,0,3],[2,1,3,12]])
Vec_rref = sp.Matrix(Vec).rref()
print(Vec_rref) ##<-- this code prints the RREF, but i am looking for the code for REF (See below)
I have found plenty of codes which solves the RREF but not codes for REF, if **it makes sense. The code i have developed gives the following:
(Matrix([
[1, 0, 2, 7],
[0, 1, -1, -2],
[0, 0, 0, 0]]), (0, 1))
I am looking for a code which should solve the following:
1XXX
REF = 01XX
001X
and not
100X
RREF = 010X
001X
New here so bare with me guys. Thanks in advance :-)
You are using the function of sympy: rref wich is associated to "reduced row-echelon form". You might want to use .echelon_form() instead
import numpy as np
import sympy as sp
from scipy import linalg
Vec = np.matrix([[1,1,1,5],
[1,2,0,3],
[2,1,3,12]])
Vec_rref =sp.Matrix(Vec).echelon_form()
print(Vec_rref)
wich outputs:
Matrix([[1, 1, 1, 5], [0, 1, -1, -2], [0, 0, 0, 0]])
I am using the following example from :
from scipy import spatial
x, y = np.mgrid[0:5, 2:8]
tree = spatial.KDTree(list(zip(x.ravel(), y.ravel())))
pts = np.array([[0, 0], [2.1, 2.9]])
idx = tree.query(pts)[1]
data = tree.data[??????????]
If I input two arbitrary points (see variable pts), I am looking to return all pairs of coordinates that lie within the rectangle defined by the two points (KDTree finds the closest neighbour). So in this case:
array([[0, 0],
[0, 1],
[0, 2],
[1, 0],
[1, 1],
[1, 2],
[2, 0],
[2, 1],
[2, 2]])
How can I achieve that from the tree data?
Seems that I found a solution:
from scipy import spatial
import numpy as np
x, y = np.mgrid[0:5, 0:5]
tree = spatial.KDTree(list(zip(x.ravel(), y.ravel())))
pts = np.array([[0, 0], [2.1, 2.2]])
idx = tree.query(pts)[1]
data = tree.data[[idx[0], idx[1]]]
rectangle = tree.data[np.where((tree.data[:,0]>=min(data[:,0])) & (tree.data[:,0]<=max(data[:,0])) & (tree.data[:,1]>=min(data[:,1])) & (tree.data[:,1]<=max(data[:,1])))]
However, I would love to see a solution using the query option!
This is the Matlab code I want to replicate in OpenCv
e[~, threshold] = edge(I, 'sobel');
fudgeFactor = .5;
BWs = edge(I,'sobel', threshold * fudgeFactor);
figure, imshow(BWs), title('binary gradient mask');
This is my test image:
Cell image
I have tried things like
blurred_gray = cv2.GaussianBlur(gray_image,(3,3),0)
sobelx = cv2.Sobel(blurred_gray,cv2.CV_8U,1,0,ksize=3)
sobely = cv2.Sobel(blurred_gray,cv2.CV_8U,0,1,ksize=3)[2]
And the output I got is:
sobelx
sobely
I tried adding sobelx and sobely because I read they're partial derivatives, but the result image looks same as the above and varying the ksize didn't help.
This is the output I need:
edge image
Could someone please tell me what I'm doing wrong and what I should do to get the same result image?
The MATLAB implementation of the sobel edge detection isn't visible so we can only guess exactly what is happening. The only hint we get is from the documentation on edge states that when the 'sobel' option is used then
Finds edges at those points where the gradient of the image I is
maximum, using the Sobel approximation to the derivative.
It's not stated, but taking the maximum of the gradient is more complicated than simply taking the local maximums in the image. Instead we want to find local maximums with respect to the gradient direction. Unfortunately the actual code used by MATLAB for this operation is hidden.
Looking at the code that is available in edge it appears that they use 4*mean(magnitude) for the threshold in the thinning operation so I'm using this combined with your fudge factor. The orientated_non_max_suppression function is far from optimal but I wrote it for readability over performance.
import cv2
import numpy as np
import scipy.ndimage.filters
gray_image = cv2.imread('cell.png', cv2.IMREAD_GRAYSCALE).astype(dtype=np.float32)
def orientated_non_max_suppression(mag, ang):
ang_quant = np.round(ang / (np.pi/4)) % 4
winE = np.array([[0, 0, 0],
[1, 1, 1],
[0, 0, 0]])
winSE = np.array([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])
winS = np.array([[0, 1, 0],
[0, 1, 0],
[0, 1, 0]])
winSW = np.array([[0, 0, 1],
[0, 1, 0],
[1, 0, 0]])
magE = non_max_suppression(mag, winE)
magSE = non_max_suppression(mag, winSE)
magS = non_max_suppression(mag, winS)
magSW = non_max_suppression(mag, winSW)
mag[ang_quant == 0] = magE[ang_quant == 0]
mag[ang_quant == 1] = magSE[ang_quant == 1]
mag[ang_quant == 2] = magS[ang_quant == 2]
mag[ang_quant == 3] = magSW[ang_quant == 3]
return mag
def non_max_suppression(data, win):
data_max = scipy.ndimage.filters.maximum_filter(data, footprint=win, mode='constant')
data_max[data != data_max] = 0
return data_max
# compute sobel response
sobelx = cv2.Sobel(gray_image, cv2.CV_32F, 1, 0, ksize=3)
sobely = cv2.Sobel(gray_image, cv2.CV_32F, 0, 1, ksize=3)
mag = np.hypot(sobelx, sobely)
ang = np.arctan2(sobely, sobelx)
# threshold
fudgefactor = 0.5
threshold = 4 * fudgefactor * np.mean(mag)
mag[mag < threshold] = 0
# non-maximal suppression
mag = orientated_non_max_suppression(mag, ang)
# alternative but doesn't consider gradient direction
# mag = skimage.morphology.thin(mag.astype(np.bool)).astype(np.float32)
# create mask
mag[mag > 0] = 255
mag = mag.astype(np.uint8)
Results on the Cell
Python
MATLAB
Results on MATLAB's peppers.png (built-in)
Python
MATLAB
The MATLAB implementation must use something a little different but it looks like this gets pretty close.
I'm trying to visualize a pair of two lists, represented by lines_x and lines_y which are meant to be plugged into the coordinates argument of either the plot function in Axes or in Lines2D.
Right now, I'm getting this result, which has extra lines compared to the result I am trying to get.
What I'm currently getting:
Previously, I tried using a loop to plot the lines one by one, and that worked for a while. However, after a few runs, it no longer worked.
Could someone please suggest a way for me to achieve the following result on my window?
The plot I want to achieve:
from pylab import *
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.pylab as plt
import matplotlib.pyplot as pltplot
import matplotlib.lines
from matplotlib.collections import LineCollection
matplotlib.use ("gTkAgg")
import numpy as np
import tkinter as tk
from tkinter import Tk
from tkinter import *
class Window (Frame):
lines_x = [-2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 0, 1, 1, 2, -2, 2, -2, -1, -1, 0]
lines_y = [0, 1, 1, 2, -2, 2, -2, -1, -1, 0, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2]
def __init__(self, parent = None):
Frame.__init__(self,parent)
parent.title("Shape Grammar Interpreter")
self.top=Frame()
self.top.grid()
self.top.update_idletasks
self.menu()
self.makeWidgets()
def makeWidgets(self):
self.f = Figure(figsize = (6,6), dpi = 100)
self.a = self.f.add_subplot(111)
#self.a.plot(self.lines_x, self.lines_y, linewidth = 4.0, picker=5)
line = Line2D(self.lines_x, self.lines_y)
self.a.add_line(line)
for i in range(len(self.lines_x)):
self.a.plot(self.lines_x[i:i+1], self.lines_y[i:i+1], linewidth = 4.0)
#self.a.plot(lines_x, lines_y, linewidth = 4.0, color = "blue")
self.a.margins(y=0.5)
self.a.margins(x=0.5)
#self.a.axes.get_xaxis().set_visible(False)
#self.a.axes.get_yaxis().set_visible(False)
# a tk.DrawingArea
self.canvas = FigureCanvasTkAgg(self.f, master=self.top)
#to show window
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
def menu(self):
menubar = Menu (root)
#to close window
menubar.add_command(label="Exit", command=self.quit_window)
root.config(menu=menubar)
def quit_window(self):
root.quit()
root.destroy()
if __name__ == "__main__":
root = Tk()
my_gui = Window(root)
root.mainloop()
It makes sense if you annotate the order in which the line segments are drawn. For example (only plotting the first 10 points, otherwise it becomes a bit of a mess):
import matplotlib.pylab as pl
lines_x = [-2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 0, 1, 1, 2, -2, 2, -2, -1, -1, 0]
lines_y = [0, 1, 1, 2, -2, 2, -2, -1, -1, 0, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2]
n = 10
pl.figure()
pl.plot(lines_x[:n], lines_y[:n])
# Number the coordinates to indicate their order:
for i in range(len(lines_x[:n])):
pl.text(lines_x[i], lines_y[i], '{}'.format(i))
pl.xlim(-3,3)
pl.ylim(-3,3)
Results in:
If I increase n, it becomes a larger mess since a number of x,y coordinates are duplicates. So:
Make sure that there are no duplicate coordinates
Make sure that the coordinates are ordered correctly.
Try these sequences instead:
lines_x = [-2, -2, -1, -1, 0, 0, 1, 1, 2, 2, -2]
lines_y = [ 0, 1, 1, 2, 2, -2, -2, -1, -1, 0, 0]
Worked for me:
Also I should note that I used simply
In [1]: import matplotlib.pyplot as plt
In [2]: plt.plot(lines_x,lines_y)
So I believe Lines has nothing to do with it.