【问题标题】:OpenCV: crop image with gaussian blurOpenCV:用高斯模糊裁剪图像
【发布时间】:2014-03-13 10:26:23
【问题描述】:

我有一个灰度图像,我想裁剪一个大小为w x h 的矩形,以像素(x,y) 为中心。问题是,我不希望裁剪看起来四四方方,所以我想对边缘进行高斯模糊,以便它们平滑过渡到零。关于如何做到这一点的任何想法?

目前我在做:

int bb_min_x = center_x - width/2.0;
int bb_max_x = center_x + width/2.0;

int bb_min_y = center_y - height/2.0;
int bb_max_y = center_y + height/2.0;

for(int y = bb_min_y; y <= bb_max_y; y++){
    for(int x = bb_min_x; x <= bb_max_x; x++){
        final_img.at<uchar>(y,x) = original_img.at<uchar>(y,x);
    }
}

【问题讨论】:

  • “高斯模糊值”是什么意思?你的描述听起来像是一个简单的淡出。模糊是不同的东西,裁剪后的模糊结果也会看起来“四四方方”。
  • @vlad_tepesch 我认为你是对的,我想要的是淡出

标签: c++ opencv image-processing gaussian


【解决方案1】:

试试这个功能:

计算与输入矩形的距离并将其用作衰减因子。

cv::Mat cropFade(cv::Mat _img, cv::Rect _roi, int _maxFadeDistance)
{
cv::Mat fadeMask = cv::Mat::ones(_img.size(), CV_8UC1);
cv::rectangle(fadeMask, _roi, cv::Scalar(0),-1);

cv::imshow("mask",fadeMask>0);

cv::Mat dt;
cv::distanceTransform(fadeMask > 0, dt, CV_DIST_L2 ,CV_DIST_MASK_PRECISE);



// fade to a maximum distance:
double maxFadeDist;

if(_maxFadeDistance > 0)
    maxFadeDist = _maxFadeDistance;
else
{
    // find min/max vals
    double min,max;
    cv::minMaxLoc(dt,&min,&max);
    maxFadeDist = max;
}


//dt = 1.0-(dt* 1.0/max);   // values between 0 and 1 since min val should alwaysbe 0
dt = 1.0-(dt* 1.0/maxFadeDist); // values between 0 and 1 in fading region

cv::imshow("blending mask", dt);


cv::Mat imgF;
_img.convertTo(imgF,CV_32FC3);


std::vector<cv::Mat> channels;
cv::split(imgF,channels);
// multiply pixel value with the quality weights for image 1
for(unsigned int i=0; i<channels.size(); ++i)
    channels[i] = channels[i].mul(dt);

cv::Mat outF;
cv::merge(channels,outF);

cv::Mat out;
outF.convertTo(out,CV_8UC3);



return out;
}

使用cv::Mat out = cropFade(in, cv::Rect(in.cols/4, in.rows/4, in.cols/2, in.rows/2), in.cols/8); 调用它会为我提供具有指定矩形的 lena 的结果:

这是完整图像从相同未更改的矩形褪色的结果:

【讨论】:

    【解决方案2】:

    一种简单的方法:

    // Create a weight image
    int border=25;
    cv::Mat_<float> rect=cv::Mat_<float>::zeros(height,width)
    cv::rectangle(rect,cv::Rect(border/2,border/2,width-border,height-border),cv::Scalar(1),-1);
    cv::Mat_<float> weights, kernel=cv::getStructuringElement(cv::MORPH_ELLIPSE,cv::Size(border,border));
    int nnz = cv::countNonZero(kernel);
    cv::filter2D(rect,weights,-1,kernel/nnz);
    

    这会创建一个重量图像,如下所示:

    然后你用它来淡出你的图像:

    for(int y = bb_min_y; y <= bb_max_y; y++){
        for(int x = bb_min_x; x <= bb_max_x; x++){
            float w = weights.at<float>(y-bb_min_y,x-bb_min_x);
            uchar val = original_img.at<uchar>(y,x);
            final_img.at<uchar>(y,x) = cv::saturate_cast<uchar>(w*val);
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您将边界框变成轮廓,您可以使用pointPolygonTest 计算每个像素到边界框边缘的距离。如果然后根据此距离将颜色值降低为零,则会获得模糊效果。

      有关示例,请参阅 this page

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-05
        • 1970-01-01
        • 1970-01-01
        • 2017-01-14
        • 1970-01-01
        • 2012-12-31
        • 1970-01-01
        • 2013-08-19
        相关资源
        最近更新 更多