c – 带掩码的OpenCV阈值

c – 带掩码的OpenCV阈值,第1张

概述我正在尝试使用OpenCV的cv :: threshold函数(更具体的THRESH_OTSU),只是我想用掩码(任何形状)来做,所以在计算过程中忽略外部(背景). 图像是单通道(必须如此),红色波纹仅用于标记图像上的示例多边形. 我尝试使用adaptiveThreshold,但有一些问题使我的情况不合适. 通常,您可以使用cv :: threshold简单地计算阈值,然后使用反转掩码在dst上复 我正在尝试使用OpenCV的cv :: threshold函数(更具体的THRESH_OTSU),只是我想用掩码(任何形状)来做,所以在计算过程中忽略外部(背景).

图像是单通道(必须如此),红色波纹仅用于标记图像上的示例多边形.

我尝试使用adaptiveThreshold,但有一些问题使我的情况不合适.

解决方法 通常,您可以使用cv :: threshold简单地计算阈值,然后使用反转掩码在dst上复制src图像.
// Apply cv::threshold on all imagethresh = cv::threshold(src,dst,thresh,maxval,type);// copy original image on inverted masksrc.copyTo(dst,~mask);

但是,使用THRESH_OTSU,您还需要仅在屏蔽图像上计算阈值.以下代码是thresh.cpp中static double getThreshVal_Otsu_8u(const Mat& _src)的修改版本:

double otsu_8u_with_mask(const Mat1b src,const Mat1b& mask){    const int N = 256;    int M = 0;    int i,j,h[N] = { 0 };    for (i = 0; i < src.rows; i++)    {        const uchar* psrc = src.ptr(i);        const uchar* pmask = mask.ptr(i);        for (j = 0; j < src.cols; j++)        {            if (pmask[j])            {                h[psrc[j]]++;                ++M;            }        }    }    double mu = 0,scale = 1. / (M);    for (i = 0; i < N; i++)        mu += i*(double)h[i];    mu *= scale;    double mu1 = 0,q1 = 0;    double max_sigma = 0,max_val = 0;    for (i = 0; i < N; i++)    {        double p_i,q2,mu2,sigma;        p_i = h[i] * scale;        mu1 *= q1;        q1 += p_i;        q2 = 1. - q1;        if (std::min(q1,q2) < FLT_EPSILON || std::max(q1,q2) > 1. - FLT_EPSILON)            continue;        mu1 = (mu1 + i*p_i) / q1;        mu2 = (mu - q1*mu1) / q2;        sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);        if (sigma > max_sigma)        {            max_sigma = sigma;            max_val = i;        }    }    return max_val;}

然后,您可以将所有函数包装在一个函数中,此处称为threshold_with_mask,它将为您包装所有不同的案例.如果没有掩码,或者掩码是全白的,则使用cv :: threshold.否则,使用上述方法之一.请注意,此包装器仅适用于CV_8UC1映像(为简单起见,您可以轻松地将其扩展为与其他类型一起使用,如果需要),并接受所有THRESH_XXX组合作为原始cv :: threshold.

double threshold_with_mask(Mat1b& src,Mat1b& dst,double thresh,double maxval,int type,const Mat1b& mask = Mat1b()){    if (mask.empty() || (mask.rows == src.rows && mask.cols == src.cols && countNonZero(mask) == src.rows * src.cols))    {        // If empty mask,or all-white mask,use cv::threshold        thresh = cv::threshold(src,type);    }    else    {        // Use mask        bool use_otsu = (type & THRESH_OTSU) != 0;        if (use_otsu)        {            // If OTSU,get thresh value on mask only            thresh = otsu_8u_with_mask(src,mask);            // Remove THRESH_OTSU from type            type &= THRESH_MASK;        }        // Apply cv::threshold on all image        thresh = cv::threshold(src,type);        // copy original image on inverted mask        src.copyTo(dst,~mask);    }    return thresh;}

以下是完整的参考代码:

#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;// ModifIEd from thresh.cpp// static double getThreshVal_Otsu_8u(const Mat& _src)double otsu_8u_with_mask(const Mat1b src,q2) > 1. - FLT_EPSILON)            continue;        mu1 = (mu1 + i*p_i) / q1;        mu2 = (mu - q1*mu1) / q2;        sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);        if (sigma > max_sigma)        {            max_sigma = sigma;            max_val = i;        }    }    return max_val;}double threshold_with_mask(Mat1b& src,~mask);    }    return thresh;}int main(){    // Load an image    Mat1b img = imread("D:\SO\img\nice.jpg",IMREAD_GRAYSCALE);    // Apply OpenCV version    Mat1b cvth;    double cvth_value = threshold(img,cvth,100,255,THRESH_OTSU);    // Create a binary mask    Mat1b mask(img.rows,img.cols,uchar(0));    rectangle(mask,Rect(100,200,200),Scalar(255),CV_FILLED);    // Apply threshold with a mask    Mat1b th;    double th_value = threshold_with_mask(img,th,THRESH_OTSU,mask);    // Show results    imshow("cv::threshod",cvth);    imshow("threshold_with_balue",th);    waitKey();    return 0;}
总结

以上是内存溢出为你收集整理的c – 带掩码的OpenCV阈值全部内容,希望文章能够帮你解决c – 带掩码的OpenCV阈值所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1236272.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存