c++ - 在 opencv 中创建晕影过滤器?

标签 c++ opencv image-processing filter computer-vision

我们如何在 opencv 中制作晕影过滤器?我们需要为它实现任何算法还是只使用 BGR 的值?我们如何制作这种类型的过滤器。我看到了它的实现 here但我没看清楚。非常感谢任何人提供完整的算法指导和实现指导。

Abid rehman K 回答后,我在 c++ 中尝试了这个

int main()
{
    Mat v;
    Mat img = imread ("D:\\2.jpg");
    img.convertTo(v, CV_32F);
    Mat a,b,c,d,e;
    c.create(img.rows,img.cols,CV_32F);
    d.create(img.rows,img.cols,CV_32F);
    e.create(img.rows,img.cols,CV_32F);

    a = getGaussianKernel(img.cols,300,CV_32F);

    b = getGaussianKernel(img.rows,300,CV_32F);


    c = b*a.t();

    double minVal;     
    double maxVal;          
    cv::minMaxLoc(c, &minVal, &maxVal);

        d = c/maxVal;
    e = v*d ;        // This line causing error
    imshow ("venyiet" , e);
    cvWaitKey();
}

d 显示正确,但 e=v*d 行导致运行时错误

OpenCV Error: Assertion failed (type == B.type() && (type == CV_32FC1 || type ==
CV_64FC1 || type == CV_32FC2 || type == CV_64FC2)) in unknown function, file ..
\..\..\src\opencv\modules\core\src\matmul.cpp, line 711

最佳答案

首先,Abid Rahman K描述了使用此过滤器的最简单方法。你应该用时间和注意力认真研究他的回答。 维基百科对 Vignetting 的看法对于那些从未听说过此过滤器的人来说也很清楚。

Browny's实现this filter要复杂得多。但是,我将他的代码移植到 C++ API 并对其进行了简化,因此您可以自己按照说明进行操作。

#include <math.h>

#include <vector>

#include <cv.hpp>
#include <highgui/highgui.hpp>


// Helper function to calculate the distance between 2 points.
double dist(CvPoint a, CvPoint b)
{
    return sqrt(pow((double) (a.x - b.x), 2) + pow((double) (a.y - b.y), 2));
}

// Helper function that computes the longest distance from the edge to the center point.
double getMaxDisFromCorners(const cv::Size& imgSize, const cv::Point& center)
{
    // given a rect and a line
    // get which corner of rect is farthest from the line

    std::vector<cv::Point> corners(4);
    corners[0] = cv::Point(0, 0);
    corners[1] = cv::Point(imgSize.width, 0);
    corners[2] = cv::Point(0, imgSize.height);
    corners[3] = cv::Point(imgSize.width, imgSize.height);

    double maxDis = 0;
    for (int i = 0; i < 4; ++i)
    {
        double dis = dist(corners[i], center);
        if (maxDis < dis)
            maxDis = dis;
    }

    return maxDis;
}

// Helper function that creates a gradient image.   
// firstPt, radius and power, are variables that control the artistic effect of the filter.
void generateGradient(cv::Mat& mask)
{
    cv::Point firstPt = cv::Point(mask.size().width/2, mask.size().height/2);
    double radius = 1.0;
    double power = 0.8;

    double maxImageRad = radius * getMaxDisFromCorners(mask.size(), firstPt);

    mask.setTo(cv::Scalar(1));
    for (int i = 0; i < mask.rows; i++)
    {
        for (int j = 0; j < mask.cols; j++)
        {
            double temp = dist(firstPt, cv::Point(j, i)) / maxImageRad;
            temp = temp * power;
            double temp_s = pow(cos(temp), 4);
            mask.at<double>(i, j) = temp_s;
        }
    }
}

// This is where the fun starts!
int main()
{
    cv::Mat img = cv::imread("stack-exchange-chefs.jpg");
    if (img.empty())
    {
        std::cout << "!!! Failed imread\n";
        return -1;
    }

    /*
    cv::namedWindow("Original", cv::WINDOW_NORMAL);
    cv::resizeWindow("Original", img.size().width/2, img.size().height/2);
    cv::imshow("Original", img);
    */

img 的样子:

    cv::Mat maskImg(img.size(), CV_64F);
    generateGradient(maskImg);

    /*
    cv::Mat gradient;
    cv::normalize(maskImg, gradient, 0, 255, CV_MINMAX);
    cv::imwrite("gradient.png", gradient);
    */

ma​​skImg 的样子:

    cv::Mat labImg(img.size(), CV_8UC3);
    cv::cvtColor(img, labImg, CV_BGR2Lab);

    for (int row = 0; row < labImg.size().height; row++)
    {
        for (int col = 0; col < labImg.size().width; col++)
        {
            cv::Vec3b value = labImg.at<cv::Vec3b>(row, col);
            value.val[0] *= maskImg.at<double>(row, col);
            labImg.at<cv::Vec3b>(row, col) =  value;
        }
    }

    cv::Mat output;
    cv::cvtColor(labImg, output, CV_Lab2BGR);
    //cv::imwrite("vignette.png", output);

    cv::namedWindow("Vignette", cv::WINDOW_NORMAL);
    cv::resizeWindow("Vignette", output.size().width/2, output.size().height/2);
    cv::imshow("Vignette", output);
    cv::waitKey();

    return 0;
}

什么是输出:

如上面的代码所述,通过改变firstPtradiuspower 的值,您可以获得更强/更弱的艺术效果。

祝你好运!

关于c++ - 在 opencv 中创建晕影过滤器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22654770/

相关文章:

iphone - 在 iPhoneSDK 中检测文档的边缘

c# - 在获得 CPU 频率方面需要一些帮助

c++ - 如何使用专用线程接收UDP数据?

c++ - 如何创建没有透明内容的完全透明窗口?

c++ - 返回 void 的预增量运算符

java - 使用 FFmpegFrameGrabber 启用 ZVBI 时如何在 Javacv 下配置 ffmpeg

c++ - OpenCV 无法设置 SVM 参数

c - 从扫描仪的输出中检测点阵图案

c++ - 在 OpenCV 应用程序中,如何确定内存泄漏的来源并修复它?

python - 使用修正的Hausdorff距离查找形状