首页 > 解决方案 > 多通道内核的图像卷积

问题描述

我想在 C++ OpenCV 库的帮助下进行三通道图像过滤。我想用 3x3 矩阵大小的内核来做到这一点,每个内核都有不同的价值。为此,我首先将 RGB 图像分为三个通道:红色、绿色和蓝色。然后我为这三个通道定义了不同的内核矩阵。然后,在函数的帮助下处理它们后filter2d,代码抛出了一个异常:

opencvTry.exe 中 0x00007FFAA150A388 处未处理的异常:Microsoft C++ 异常:内存位置 0x0000002D4CAF9660 处的 cv::Exception。发生了

我不能在下面的代码中执行此操作的原因是什么?

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <typeinfo>
#include <stdlib.h>

using namespace cv;
using namespace std;

int main()
{
Mat src = imread("path\\color_palette.png", IMREAD_COLOR); //load  image


int blue_array[159][318];
int green_array[159][318];
int red_array[159][318];
for (int i = 0; i < src.rows; i++) {
    for (int j = 0; j < src.cols; j++) {
        int a = int(src.at<Vec3b>(i, j).val[0]);
        blue_array[i][j] = a;
        //cout << blue_array[i][j] << ' ' ;
        int b = int(src.at<Vec3b>(i, j).val[1]);
        green_array[i][j] = b;
        int c = int(src.at<Vec3b>(i, j).val[2]);
        red_array[i][j] = c;
    }
}



cv::Mat blue_array_mat(159, 318, CV_32S, blue_array);
cv::Mat green_array_mat(159, 318, CV_32S, green_array);
cv::Mat red_array_mat(159, 318, CV_32S, red_array);



float kernelForBlueData[9]  = { 1,0,1, 2,0,-2, 1,0,-1};
cv::Mat kernelForBlue(3, 3, CV_32F, kernelForBlueData);
float  kernelForGreenData[9] = { 1./16, 2./16, 1./16, 2./16, 4./16,2./16, 1./16, 2./16, 1./16 };
cv::Mat kernelForGreen(3, 3, CV_32F,  kernelForGreenData);
float  kernelForRedData[9]  = { 1./9,1./9, 1./9, 1./9, 1./9,1./9, 1./9, 1./9,1./9 };
cv::Mat kernelForRed(3, 3, CV_32F,  kernelForRedData);



//cv::filter2D(blue_array_mat, blue_array_mat, -1, kernelForBlue, Point(-1, -1), 5.0, BORDER_REPLICATE);
filter2D(blue_array_mat, blue_array_mat, 0, kernelForBlue);

imshow("filter", blue_array_mat);



waitKey(0);
return 0;
}

标签: c++opencvimage-processingconvolution

解决方案


您正在使用一个构造函数,cv::Mat该构造函数需要一个指向数据的指针(例如int*),但您将其int**放入其中。我想这就是崩溃的原因。

为什么不cv::Mat先创建然后直接写入数据呢?

请注意,OpenCV 有一个功能可以为您执行此操作:

cv::Mat chans[3];
cv::split(src, chans);
//...
cv::filter2D(chans[2], chans[2], 0, kernelForBlue);

推荐阅读