How can I take inverse Fourier transform of an image twice? - python

I want to apply the inverse discrete Fourier transform on the image twice. For this I did the following:
img = cv2.imread("a.png", 0)
img_back = cv2.idft(cv2.idft(img))
cv2.imwrite("f.png", img_back)
But I get an error saying:
Traceback (most recent call last):
File "test2.py", line 26, in <module>
img_back = cv2.idft(cv2.idft(img))
cv2.error: OpenCV(4.0.0) /Users/travis/build/skvark/opencv-python/opencv/modules/core/src/dxt.cpp:3335: error: (-215:Assertion failed) type == CV_32FC1 || type == CV_32FC2 || type == CV_64FC1 || type == CV_64FC2 in function 'dft'
I cannot understand the reason for this. How could I take the inverse fourier transform of the image twice?

The error message tells you that the input to the idft function must be 32-bit or 64-bit float, with one or two channels (complex data is represented as two channels).
This error happens because img is an integer type (as expected because you read it in from a PNG file). To correct it, convert it to a floating-point type:
img = cv2.imread("a.png", 0)
img = img.astype('f')
img_back = cv2.idft(cv2.idft(img))

Related

How to convert python np.array to cv2 image

Following code:
img = np.array([[[1,2,4]]])
cv2.subtract(img, tuple([1.0]))
Results in error:
Traceback (most recent call last): File "", line 1, in
cv2.error: OpenCV(4.4.0)
C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-nxx381if\opencv\modules\core\src\arithm.cpp:671:
error: (-215:Assertion failed) type2 == CV_64F && (sz2.height == 1 ||
sz2.height == 4) in function 'cv::arithm_op'
If I change the img to:
img = np.array([[[1,2,4],[1,2,4],[1,2,4],[1,2,4],[1,2,4]]])
Then it works correctly
In my case I have images of different sizes mono and color and I want to subtract constant value with saturation. The Shapes are HxWx1 or HxWx3 (different datatypes)
How to correctly use cv2.subtract for such cases ?
Edit:
I would like to keep high performance and avoid to allocate temporary arrays / types conversions
You can just subtract a constant value from a numpy array:
img = np.array([[[1,2,4],[1,2,4],[1,2,4],[1,2,4],[1,2,4]]])
img_new=img-1
or if you want to use cv2.substract:
constant = 3
img_new_2=cv2.subtract(img, constant*np.ones(img.shape).astype(type(img[0,0,0])))
edit:
if you want to show this image using opencv you have to convert it to a valid type.
cv2.imshow("window", img_new_2.astype(np.int8))
cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV error: bitwise_and throws error that mask and image are not same size

I am trying to apply a mask I have made to an image using openCV (3.3.1) in python (3.6.5) to extract all the skin. I am looping over a photo and checking windows and classifying them using two premade sklearm GMMs. If the window is skin I have changing that area of the mask to True (255) otherwise leaving it as 0.
I have initialized the numpy array to hold the mask before the loop to be the same dimensions as the image, but openCV keeps saying that the image and mask do not have the same dimensions (output and error message are below). I have seen other somewhat similar problems on the site but none with solutions that have worked for me.
Here is my code:
# convert the image to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
delta = 6
# create an empty np array to make the mask
#mask = np.zeros((img.shape[0], img.shape[1], 1))
mask = np.zeros(img.shape[:2])
# loop through image and classify each window
for i in range(0,hsv.shape[0],delta):
for j in range(0,hsv.shape[1],delta):
# get a copy of the window
arr = np.copy(hsv[i:i+delta,j:j+delta,0])
# create a normalized hue histogram for the window
if arr.sum() > 0:
arr = np.histogram(np.ravel(arr/arr.sum()), bins=100, range=(0,1))
else:
arr = np.histogram(np.ravel(arr), bins=100, range=(0,1))
# take the histogram and reshape it
arr = arr[0].reshape(1,-1)
# get the probabilities that the window is skin or not skin
skin = skin_gmm.predict_proba(arr)
not_skin = background_gmm.predict_proba(arr)
if skin > not_skin:
# becasue the window is more likely skin than not skin
# we fill that window of the mask with ones
mask[i:i+delta,j:j+delta].fill(255)
# apply the mask to the original image to extract the skin
print(mask.shape)
print(img.shape)
masked_img = cv2.bitwise_and(img, img, mask = mask)
The output is:
(2816, 2112)
(2816, 2112, 3)
OpenCV Error: Assertion failed ((mtype == 0 || mtype == 1) &&
_mask.sameSize(*psrc1)) in cv::binary_op, file C:\ci\opencv_1512688052760
\work\modules\core\src\arithm.cpp, line 241
Traceback (most recent call last):
File "skindetector_hist.py", line 183, in <module>
main()
File "skindetector_hist.py", line 173, in main
skin = classifier_mask(img, skin_gmm, background_gmm)
File "skindetector_hist.py", line 63, in classifier_mask
masked_img = cv2.bitwise_and(img, img, mask = mask)
cv2.error: C:\ci\opencv_1512688052760\work\modules\core\src
\arithm.cpp:241: error: (-215) (mtype == 0 || mtype == 1) &&
_mask.sameSize(*psrc1) in function cv::binary_op
As you can see in the output, the image and mask have the same width and height. I have also tried making the mask have depth one (line 5) but that didn't help. Thank you for any help!
It is not only complaining about the size of the mask. It is complaining about the type of the mask. The error:
OpenCV Error: Assertion failed ((mtype == 0 || mtype == 1) &&
_mask.sameSize(*psrc1))
Means that either the type of the mask or the size (that in your case is equal) is not the same. In the documentation we see:
mask – optional operation mask, 8-bit single channel array, that
specifies elements of the output array to be changed.
And this is consistent with the error that asks for a type 0 (CV_8U) or 1 (CV_8S).
Also, even if it is not said, the img should not be float, since it will not give a desired result (probably it will do it anyways).
The solution is probably enough to change:
mask = np.zeros(img.shape[:2])
to
mask = np.zeros(img.shape[:2], dtype=np.uint8)
A small test shows what type you will get:
np.zeros((10,10)).dtype
gives you dtype('float64') which means doubles and not 8 bit

Python - Displaying the image with the original colors

In the answer to this question, I wanted to display the image in its original colors, and so removed the gray parameter from this line of code:
plt.imshow(im_out, 'gray')
When doing this however I get the image displayed with yellow and purple colors as opposed to the image's original colors.
What should I do to display the image with its original colors?
Thanks.
EDIT 1 I came across this tutorial, and seems that I should use:
plt.imshow(cv2.cvtColor(im_out, cv2.COLOR_BGR2RGB))
However, when I did this, I got the following:
Calculated scale difference: 0.99
Calculated rotation difference: 44.51
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor, file /home/user/opencv/modules/imgproc/src/color.cpp, line 10606
Traceback (most recent call last):
File "align_surf.py", line 47, in <module>
deskew()
File "align_surf.py", line 9, in deskew
plt.imshow(cv2.cvtColor(im_out, cv2.COLOR_BGR2RGB))
cv2.error: /home/user/opencv/modules/imgproc/src/color.cpp:10606: error: (-215) scn == 3 || scn == 4 in function cvtColor
How can I fix this issue?
EDIT 2 The reason of the above was that the image was read as follows in the original code:
orig_image = cv2.imread('1.jpg', 0)
So, I simply removed 0.
Based on this tutorial, in order to fix the issue, I had to convert BGR to RGB, as follows:
plt.imshow(cv2.cvtColor(im_out, cv2.COLOR_BGR2RGB))

compare Image similarity using HOG

Using python we need to find similarities between any type of image.
In the below code snippet, we are reading all images from the folder and extracting the histograms from them and storing the histograms in hashtable for comparision.
for imagePath in paths.list_images(imagesfolderpath):
image = cv2.imread(imagePath)
if image is None or len(image)<=112:
print()
else:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
winStride = (8,8)
padding = (8,8)
locations = ((10,20),)
hist = hog.compute(image,winStride,padding,locations)
labels.append(imagePath.split("/")[-2])
if len(hist)>0:
data.append(hist)
hashtable[imagePath] = hist
below code snippet is used for histogram comparision
for key, value in hashtable.iteritems():
count+=1
mydir = os.path.join(outpath, datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S-%f'))
os.makedirs(mydir)
for key1, value1 in hashtable.iteritems():
score = cv2.compareHist(np.array(value, dtype=np.int8),np.array(value1, dtype=np.int8), cv2.HISTCMP_BHATTACHARYYA)
While histogram comparision the error encountered is as follows:
OpenCV Error: Assertion failed (H1.type() == H2.type() && H1.depth() == CV_32F) in compareHist, file /home/administrator/Desktop/vijay/openface/opencv-3.0.0/modules/imgproc/src/histogram.cpp, line 2281
Traceback (most recent call last):
File "TestHOG.py", line 118, in <module>
score = cv2.compareHist(np.array(value, dtype=np.int8),np.array(value1, dtype=np.int8), cv2.HISTCMP_BHATTACHARYYA)
cv2.error: /home/administrator/Desktop/vijay/openface/opencv-3.0.0/modules/imgproc/src/histogram.cpp:2281: error: (-215) H1.type() == H2.type() && H1.depth() == CV_32F in function compareHist

How to use orb on a image in CV2?

I wish to use ORB (http://docs.opencv.org/3.1.0/d1/d89/tutorial_py_orb.html#gsc.tab=0) on a 28*28 grayscale image (handwritten digits), where each pixel has a number from 0 to 255.
This is the code I used:
# image = {load the array of 754 numbers}
orb = cv2.ORB_create()
image = image.reshape(28, 28))
kp = orb.detect(image, None)
But I keep getting this error:
OpenCV Error: Assertion failed (depth == CV_8U || depth == CV_16U || depth == CV_32F) in cvtColor, file /home/yahya/Documents/_other_downloaded_apps/opencv/modules/imgproc/src/color.cpp, line 7935
Traceback (most recent call last):
File "/home/yahya/Documents/hello.py", line 118, in <module>
kp = orb.detect(image, None)
cv2.error: /home/yahya/Documents/_other_downloaded_apps/opencv/modules/imgproc/src/color.cpp:7935: error: (-215) depth == CV_8U || depth == CV_16U || depth == CV_32F in function cvtColor
How can I do this and why am I getting this error?
UPDATE
I seemed to have solved part of this problem. It turns out that orb accepts float32 numbers (not 64).
Therefore I updated my code as follows:
orb = cv2.ORB_create()
image = feature_x[0].reshape(28, 28).astype('float32')
kp = orb.detect(image, None)
But now I have the following error:
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in ipp_cvtColor, file /home/yahya/Documents/_other_downloaded_apps/opencv/modules/imgproc/src/color.cpp, line 7456
Traceback (most recent call last):
File "/home/yahya/Documents/hello.py", line 188, in <module>
kp = orb.detect(image, None)
cv2.error: /home/yahya/Documents/_other_downloaded_apps/opencv/modules/imgproc/src/color.cpp:7456: error: (-215) scn == 3 || scn == 4 in function ipp_cvtColor
The image you are trying to load isn't compatible type for the orb. You should convert it first before using it. Also you don't need reshape if you are loading it into numpy array
orb = cv2.ORB_create()
image = image.astype(np.uint8, copy=False)
kp = orb.detect(image, None)

Categories