OpenCv - 为DCT实现拆分和合并

时间:2014-04-10 09:49:20

标签: java android opencv image-processing

我正在尝试在Android中实现DCT代码。我正在使用拆分和合并方法来获取图像的原始颜色。

以下是代码的片段

image = Highgui.imread(imageName);  

secondImage = new Mat(image.rows(), image.cols(), CvType.CV_32FC3);
image.convertTo(secondImage, CvType.CV_32FC3);

int m = Core.getOptimalDFTSize(image.rows());
int n = Core.getOptimalDFTSize(image.cols()); // on the border add zero values

Mat padded = new Mat(new Size(n, m), CvType.CV_32FC3); // expand input image to optimal size

Imgproc.copyMakeBorder(secondImage, padded, 0, m - secondImage.rows(), 0, n - secondImage.cols(), Imgproc.BORDER_CONSTANT);

List<Mat> planes = new ArrayList<Mat>();

Core.split(padded, planes);
List<Mat> outplanes = new ArrayList<Mat>(planes.size());
for (int k = 0; k < planes.size(); k++) { 
    outplanes.add(new Mat(padded.size(), CvType.CV_32FC1)); 
} 

Mat trans = new Mat(padded.size(), padded.type());  

for (int k = 0; k < planes.size(); k++) { 
    Core.dct(planes.get(k), outplanes.get(k));  
} 

List<Mat> ioutplanes = new ArrayList<Mat>(outplanes.size());
for (int k = 0; k < planes.size(); k++) { 
    ioutplanes.add(new Mat(padded.size(), CvType.CV_32FC1)); 
}   

for (int k = 0; k < planes.size(); k++) {
    Core.idct(outplanes.get(k), ioutplanes.get(k));  
} 
Core.merge(ioutplanes, trans); 

这次有例​​外:

  

在void cv :: dct(cv :: InputArray,cv :: OutputArray,int),file / home / reports / ci / slave_desktop / 50中未实现函数/功能(未实现奇数DCT) -SDK / opencv / modules / core / src / dxt.cpp,第2330行

这段代码是否正确?非常感谢您的帮助。

更新:我注意到copyMakeBorder()是导致我的图片大小为奇数的那个,这就是我遇到此异常的原因。

3 个答案:

答案 0 :(得分:0)

SIGSEGV是一个分段错误,通常在程序试图访问它没有权限或无法访问的内存部分时抛出。我的想法是,这是由于硬件,可能是操作的内存太少。

您是否尝试使用较小的样本或其他计算机运行程序?

答案 1 :(得分:0)

secondImage和padded将是类型:CvType.CV_32FC3。还有就地转换,如:

   planes.get(k).convertTo(planes.get(k), CvType.CV_32FC1); 

我不确定是否有效,所以如果你需要进行这种转换,请使用中间Mat。另请注意,填充已经是CV_32F,因此不确定是否需要执行此转换。同样来自dct的输出 - 如果这是CV_32F则不需要转换。

如果要显示合并的图片,您当然需要将每个通道值标准化为0到255之间。

看起来你正在应用dct变换然后反向直接,所以你将回到你的开始。我认为我们还需要注意像outplanes.addAll(飞机)之类的调用,因为我认为这只是添加对象的引用而不是分配空间,这正是你想要的。

试试这个:

Imgproc.copyMakeBorder(secondImage, padded, 0,
                m - secondImage.rows(), 0, n - secondImage.cols(),
                Imgproc.BORDER_CONSTANT);

List<Mat> planes = new ArrayList<Mat>();

Core.split(padded, planes);

Mat trans = new Mat(padded.size(), padded.type());

List<Mat> ioutplanes = new ArrayList<Mat>(planes.size());

for (int k = 0; k < planes.size(); k++) {
    ioutplanes.add(new Mat(padded.size(), CvType.CV_32FC1));
}

for (int k = 0; k < planes.size(); k++) {
    Core.idct(planes.get(k), ioutplanes.get(k));
}

Core.merge(ioutplanes, trans);

答案 2 :(得分:0)

也许你可以改变这段代码

int m = Core.getOptimalDFTSize(image.rows());
int n = Core.getOptimalDFTSize(image.cols());

int m =Core.getOptimalDFTSize((image.rows()+1)/2)*2;
int n = Core.getOptimalDFTSize((image.cols()+1)/2)*2;

以获得DCT的奇数大小,因为此函数用于DFT。

它写在网站的功能文档中:

虽然该函数不能直接用于估计DCT变换的最佳矢量大小(因为当前的DCT实现仅支持偶数大小的矢量),但它可以很容易地处理为getOptimalDFTSize((vecsize + 1)/ 2)* 2。