在opencv中创建晕影过滤器? [英] Creating vignette filter in opencv?

查看:292
本文介绍了在opencv中创建晕影过滤器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们如何在opencv中创建晕影过滤器?我们需要为它实现任何算法还是只使用BGR的值?我们如何使这种类型的过滤器。我看到它的实现这里,但我不明白它。



之后 c>回答我在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();
}

e = v * d 行导致

的运行时错误
$ b

  OpenCV错误:断言失败(类型== B.type()&&(type == CV_32FC1 || type == 
CV_64FC1 || type == CV_32FC2 || type == CV_64FC2))未知函数,file ..
\ ... \..\src\opencv\modules\core\src\matmul.cpp,第711行


解决方案

首先, Abid Rahman K 介绍了使用此过滤器的最简单方法。 维基百科对暗角的采纳是也非常清楚那些从未听说过这个过滤器的人。



Browny的实施此过滤器相当复杂。但是,我将他的代码移植到C ++ API并简化它,所以你可以按照说明自己。

  #include< math.h> 

#include< vector>

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


//帮助函数计算2点之间的距离。
double dist(CvPoint a,CvPoint b)
{
return sqrt(pow((double)(ax-bx),2)+ pow(double(ay-by) 2));
}

//帮助函数,计算从边到中心点的最长距离。
double getMaxDisFromCorners(const cv :: Size& imgSize,const cv :: Point& center)
{
//给定一个直线和一条线
//得到rect距离行最远

std :: vector< cv :: Point>角(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;
}

//帮助函数创建一个渐变图像。
// firstPt,radius和power,是控制过滤器的艺术效果的变量。
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 {
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;
}
}
}

//这是乐趣开始的地方!
int main()
{
cv :: Mat img = cv :: imread(stack-exchange-chefs.jpg);
if(img.empty())
{
std :: cout< !!! Failed imread\\\
;
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);
* /

maskImg 类似:



  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 (row.Col);(b)(b)(b)(b)(c)
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;
}

输出





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



祝你好运!


How we can make vignette filter in opencv? Do we need to implement any algorithm for it or only to play with the values of BGR ? How we can make this type of filters. I saw its implementation here but i didn't understand it clearly . Anyone with complete algorithms guidance and implementation guidance is highly appriciated.

After Abid rehman K answer I tried this in 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 is displaying right but e=v*d line is causing runtime error of

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

解决方案

First of all, Abid Rahman K describes the easiest way to go about this filter. You should seriously study his answer with time and attention. Wikipedia's take on Vignetting is also quite clarifying for those that had never heard about this filter.

Browny's implementation of this filter is considerably more complex. However, I ported his code to the C++ API and simplified it so you can follow the instructions yourself.

#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);
    */

What img looks like:

    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);
    */

What maskImg looks like:

    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;
}

What output looks like:

As stated in the code above, by changing the values of firstPt, radius and power you can achieve stronger/weaker artistic effects.

Good luck!

这篇关于在opencv中创建晕影过滤器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆