用Python实现二维离散余弦变换的ISSUE

用Python实现二维离散余弦变换的ISSUE,python,matlab,dct,Python,Matlab,Dct,我正试图将赵科赫的隐写术方法从matlab改写成python,我在一开始就被卡住了 matlab中的前两个过程: 步骤1: A = imread(casepath); # Reading stegonography case image and aquiring it's RGB values. In my case it's a 400x400 PNG image, so it gives a 400x400x3 array. 步骤2: D = dct2(A(:,:,3)); # Apply

我正试图将赵科赫的隐写术方法从matlab改写成python,我在一开始就被卡住了

matlab中的前两个过程:

步骤1:

A = imread(casepath); # Reading stegonography case image and aquiring it's RGB values. In my case it's a 400x400 PNG image, so it gives a 400x400x3 array.
步骤2:

D = dct2(A(:,:,3)); # Applying 2D DCT to blue values of the image
Python代码模拟:

from scipy import misc
from numpy import empty,arange,exp,real,imag,pi
from numpy.fft import rfft,irfft

arr = misc.imread('casepath')# 400x480x3 array (Step 1)
arr[20, 30, 2] # Getting blue pixel value

def dct(y): #Basic DCT build from numpy
    N = len(y)
    y2 = empty(2*N,float)
    y2[:N] = y[:]
    y2[N:] = y[::-1]

    c = rfft(y2)
    phi = exp(-1j*pi*arange(N)/(2*N))
    return real(phi*c[:N])


def dct2(y): #2D DCT bulid from numpy and using prvious DCT function
    M = y.shape[0]
    N = y.shape[1]
    a = empty([M,N],float)
    b = empty([M,N],float)

    for i in range(M):
        a[i,:] = dct(y[i,:])
    for j in range(N):
        b[:,j] = dct(a[:,j])

    return b

 D = dct2(arr) # step 2 anlogue
但是,当我尝试执行代码时,我得到以下错误:

Traceback (most recent call last):
File "path to .py file", line 31, in <module>
D = dct2(arr)
File "path to .py file", line 25, in dct2
a[i,:] = dct(y[i,:])
File "path to .py file", line 10, in dct
y2[:N] = y[:]
ValueError: could not broadcast input array from shape (400,3) into shape (400)
回溯(最近一次呼叫最后一次):
文件“指向.py文件的路径”,第31行,在
D=dct2(arr)
文件“指向.py文件的路径”,第25行,在dct2中
a[i,:]=dct(y[i,:])
文件“指向.py文件的路径”,第10行,dct格式
y2[:N]=y[:]
ValueError:无法将输入数组从形状(400,3)广播到形状(400)
也许有人能向我解释一下我做错了什么

其他信息: 操作系统:Windows 10 Pro 64位 Python:2.7.12 scipy:0.18.1 numpy:1.11.2
pillow:3.4.1

您的代码运行良好,但它设计为只接受2D数组,就像在Matlab中一样。由于您的
arr
是一个3D阵列,因此您需要执行以下操作:

D = dct2(arr[...,2])
正如我在评论中提到的,使用scipy包中的(fast)内置程序,而不是重新发明轮子

我的评论中链接中的代码有效地为您提供了以下信息:

import numpy as np
from scipy.fftpack import dct, idct

def dct2(block):
    return dct(dct(block.T, norm='ortho').T, norm='ortho')

def idct2(block):
    return idct(idct(block.T, norm='ortho').T, norm='ortho')
但是,我必须再次强调,必须分别为每个颜色平面调用此函数。Scipy的
dct()
将愉快地接受任何N维数组,并将在最后一个轴上应用变换。因为这是你的颜色平面,而不是你的像素行和列,你会得到错误的结果。是的,有一种方法可以通过
axis
输入参数来解决这个问题,但我不会不必要地使这个答案过于复杂



关于这里涉及的各种DCT实现,如果您从上面的代码片段中省略
norm='ortho'
参数,那么您的版本和scipy的实现将给出相同的结果。但如果包含该参数,scipy的转换将与Matlab的一致。

您的代码运行良好,但它的设计仅接受2D数组,就像在Matlab中一样。由于您的
arr
是一个3D阵列,因此您需要执行以下操作:

D = dct2(arr[...,2])
正如我在评论中提到的,使用scipy包中的(fast)内置程序,而不是重新发明轮子

我的评论中链接中的代码有效地为您提供了以下信息:

import numpy as np
from scipy.fftpack import dct, idct

def dct2(block):
    return dct(dct(block.T, norm='ortho').T, norm='ortho')

def idct2(block):
    return idct(idct(block.T, norm='ortho').T, norm='ortho')
但是,我必须再次强调,必须分别为每个颜色平面调用此函数。Scipy的
dct()
将愉快地接受任何N维数组,并将在最后一个轴上应用变换。因为这是你的颜色平面,而不是你的像素行和列,你会得到错误的结果。是的,有一种方法可以通过
axis
输入参数来解决这个问题,但我不会不必要地使这个答案过于复杂



关于这里涉及的各种DCT实现,如果您从上面的代码片段中省略
norm='ortho'
参数,那么您的版本和scipy的实现将给出相同的结果。但包含该参数后,scipy的转换将与Matlab的一致。

来自numpy和scipy,您可以直接访问。你对自己的慢动作感兴趣吗?谢谢,我不知道,只是试了一下。看起来效果不错。从numpy和scipy您可以直接访问。你对自己的慢动作感兴趣吗?谢谢,我不知道,只是试了一下。看起来效果不错。