How to polyfit() an OpenCV calcHist() histogram? - python

I have something like this:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
import numpy.polynomial.polynomial as poly
img = cv.imread('SomeImage.jpg')
color = ('b','g','r')
for i,col in enumerate(color):
histr = cv.calcHist([img],[i],None,[32],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,32])
x = np.linspace(0,histr.shape[0],1); # <== ERROR HERE
poly.polyfit(x, histr, 4)
I get the following error:
File "/Users/case/anaconda2/lib/python2.7/site-packages/numpy/polynomial/polynomial.py", line 1438, in polyfit
raise TypeError("expected x and y to have same length")
TypeError: expected x and y to have same length
I'm pretty new to this, but seems I'm missing something simple?

It looks like a minor syntax mistake when calling np.linspace. The correct syntax is
x = np.linspace(interval_start, interval_end, number_of_points)
so in your case, that would be
x = np.linspace(0, 1, histr.shape[0])

Related

Plot with conditional data

I have a file abc.dat having data set with column "ec", "ev", "eig", "ep". I have to plot E vs x graph. Here the values for x, E and other variables related to this are given below.
import numpy as np
import matplotlib.pyplot as plt
data = np.loadtxt('/Users/abc.dat')
ec = data[0:,0]
ev = data[0:,1]
eig = data[0:,2]
ep = data[0:,3]
a=(eig-(ec-ev))
A= 5
B=1/eig**2
for x in range(1,500):
g=(1/(0.5* np.sqrt(2*3.14)))* np.exp((-(x-eig)**2)/(2*(0.5)**2))
ep_1=(ep*g)**2
P=sum(ep_1)
for i in a:
if i==0:
D=1
else:
D=0
e=A*B*P*D
plt.plot(x,e)
Your code has the plt.plot() command buried in loops, which is probably not what you are trying to do. You will need x to be an array the same size as e, and from your question it might have fewer points than you expect since it has shape (409,).
Try this:
import numpy as np
import matplotlib.pyplot as plt
data = np.loadtxt('/Users/abc.dat')
ec = data[0:,0]
ev = data[0:,1]
eig = data[0:,2]
ep = data[0:,3]
a=(eig-(ec-ev))
A= 5
B=1/eig**2
x = np.arange(len(eig))
g=(1/(0.5* np.sqrt(2*3.14)))* np.exp((-(x-eig)**2)/(2*(0.5)**2))
P=((g*np.broadcast_to(ep, (len(g), len(ep))).T)**2).sum(axis=0)
e=np.where(a==0, A*B*P, 0)
plt.plot(x,e)
I am not sure from the question if I have the logic for P calculating as you want it to.

Trying to Plot FFT for an Image Array

I'm trying to create a signal plot for an array of pictures using the following code:
import numpy as np
import sys
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
imgArr = {}
stnArr = {}
frmArr = {}
sgnArr = {}
for i in range(1,2397):
imgArr[i] = mpimg.imread("20210209_themis_rank"+ str(i)+ ".png")
stnArr[i] = np.mean([imgArr[i]]/std(imgArr[i]))
frmArr[i] = i
signal = np.fft.fft(imgArr[i])
for i in range(1,2397):
plt.plot(frmArr,np.abs(signal))
plt.show()
However, I keep on running into the following error. How can I get it to work?
raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (1,) and (600, 600, 4)

To fix an error : could not broadcast input array from shape (5,5) into shape (5,5,4)

I want to preprocess such an image dataset using an unsupervised wiener algorithm. But it doesn't work properly. when I run the code, it shows me a value attribute error. For convenience, my code is given below -
import cv2
import glob
from matplotlib import pyplot as plt
from skimage import io, restoration, img_as_float
import scipy.stats as st
import numpy as np
dataset = glob.glob('input/train/*.png')
directory = 'output/train/'
for img_id, img_path in enumerate(dataset):
img = img_as_float(io.imread(img_path))
def gkern(kernlen=21, nsig=2): #Returns a 2D Gaussian kernel.
lim = kernlen//2 + (kernlen % 2)/2
x = np.linspace(-lim, lim, kernlen+1)
kern1d = np.diff(st.norm.cdf(x))
kern2d = np.outer(kern1d, kern1d)
return kern2d/kern2d.sum()
psf = gkern(5,3) #Kernel length and sigma
deconvolved, _ = restoration.unsupervised_wiener(img, psf)
cl2 = cv2.resize(deconvolved, (512,512), interpolation = cv2.INTER_CUBIC)
plt.imsave(f"output/unsupervised_{img_id}.png", cl2, cmap='gray')
I am getting the error :
File "C:\Users\Junaed\.spyder-py3\unsupervised_wiener.py", line 33, in <module>
deconvolved, _ = restoration.unsupervised_wiener(img, psf)
ValueError: could not broadcast input array from shape (5,5) into shape (5,5,4)
How could I fix this issue, Can someone help me here?

Get a three dimensional array as a parameter and return a three dimensional arrays

I have to write a function to_red that should zero out the green and blue color components and return the result. I wrote the below code for an Image(.png) to zero out green and blue color and return red and it worked. However, as mentioned in title, the input parameter has to be a 3-d array and return a 3-d array. How should my below code be changed for that.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
def to_red()
src = plt.imread("C:\src\painting.png")
red_channel = src[:,:,0]
red_img = np.zeros(src.shape)
red_img[:,:,0] = red_channel
plt.imshow(red_img)
plt.show()
You can write your function like this:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
def to_red(src):
# Check if the input dimension is 3
if not src.ndim == 3:
# Raise exception or do something
print ("Dimension mismatch")
return 0
red_channel = src[:,:,0]
red_img = np.zeros(src.shape)
red_img[:,:,0] = red_channel
return red_img
And then you can call it like this
source_image = plt.imread("C:\src\painting.png")
red_image = to_red(source_image)
plt.imshow(red_image)
plt.show()
I also added a line to check if the input is actually 3 dimensional.
You can use numpy's powerful indexing capabilities
def to_red(src):
ret = a.copy()
ret[:,:,1:] = 0
return ret

Python plot only part of data

I want to plot any part or the data
here is the code
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
... ...
xs = []
avg = []
for line in lines:
if len(line) > 1:
x, y1 = line.split(',')
xs.append(float(x))
avg.append(float(y1))
ax1.plot(xs, avg, label='avg')
I added some of the code so you can see the type of the variables
I tried :
ax1.plot(xs[avg>0], avg[avg>0], label='avg')
and didnt work
im matlab i would do some thing like :
Indxs=find (ys>0)
Plot(xs(indxs),ys(indxs))
The syntax is correct. The problem is that xs and avg are no numpy arrays. So you first need to convert those lists to numpy arrays, then the slicing will work as expected.
xs = np.array(xs)
avg = np.array(avg)
ax1.plot(xs[avg>0], avg[avg>0], label='avg')
What you doesen't work since your index (avg > 0) in python is a boolean. When you are used to Matlab then you should definitely try numpy Boolean indexing.
you can do:
import numpy as np
xs = numpy.asarray(x)
ys = numpy.asarray(y)
ys_filtered = ys[x > 0]

Categories