OpenCV開發筆記(三十一):紅胖子8分鐘帶你深刻了解雙閾值化(圖文並貌+淺顯易懂+程序源碼)

若該文爲原創文章,未經容許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104858803
各位讀者,知識無窮而人力有窮,要麼改需求,要麼找專業人士,要麼本身研究算法

紅胖子(紅模仿)的博文大全:開發技術集合(包含Qt實用技術、樹莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機、軟硬結合等等)持續更新中...(點擊傳送門)數組

OpenCV開發專欄(點擊傳送門)

上一篇:OpenCV開發筆記(三十):帶你學習圖像識別之經典OTSU算法閾值化函數

下一篇:OpenCV開發筆記(三十二):紅胖子8分鐘帶你深刻了解半閾值化(圖文並貌+淺顯易懂+程序源碼)學習

 

前言

紅胖子來也!!!ui

今天來講說雙閾值化,雙閾值化能夠理解爲是對閾值化的操做升級,關鍵是加了矩陣像素點與或非的這麼一個操做,嘿!別小看與或非,這個操做未來用處可大了,尤爲是分離圖像處理,疊加圖像。url

 

Demo

 

雙閾值化

概述

       對於圖像中有明顯的雙分界特徵,能夠優先考慮雙閾值方法進行二值化的操做,根據雙閾值化的操做,能夠假定一個下限閾值和一個上限閾值,當像素點的值在上下限閾值範圍內,則達到閾值,低於下限和高於上限則不作操做。spa

       假設,灰度圖像分爲0~255級別,當咱們須要中間100~200進行閾值化,那麼能夠設置下限100和上限200,那麼區間[0,100]和{200,255]則與區間(100,200)能夠分割開。.net

       推到公式以下:code

閾值化函數原型

double threshold( InputArray src,
                  OutputArray dst,
                  double thresh,
                  double maxval,
                  int type );
  • 參數一:InputArray類型,通常是cv::Mat,且能夠處理多通道,8或者32位浮點(注意:當使用THRESH_BINARY處理多通道的時候,每一個通道都會進行閾值化,好比RGB三通道,那麼可能R比G,B大,當閾值設置爲大於G、B小於R時,則R爲最大是,顯示紅色,其餘類型的閾值形式類推)。
  • 參數二;OutputArray類型,輸出的目標圖像,須要和原圖片有同樣的尺寸和類型。
  • 參數三:double類型的thresh,閾值。
  • 參數四:double類型的maxval,與「THRESH_BINARY」枚舉和「THRESH_BINARY_INV」枚舉一塊兒使用纔有效果,其餘枚舉忽略。
  • 參數五:int類型的type,閾值類型。

與或非操做函數原型

void bitwise_and(InputArray src1,
                 InputArray src2,
                 OutputArray dst,
                 InputArray mask = noArray());
  • 參數一:InputArray類型,通常是cv::Mat。
  • 參數二:InputArray類型,通常是cv::Mat。
  • 參數三;OutputArray類型,輸出的目標圖像,須要和原圖片有同樣的尺寸和類型。
  • 參數四:InputArray類型mask,掩碼可選操做掩碼,8位單通道陣列指定要更改的輸出數組的元素。

 

Demo源碼

void OpenCVManager::testDoubleThreshold()
{
    QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/8.jpg";
    cv::Mat srcMat = cv::imread(fileName1.toStdString());

    int width = 300;
    int height = 200;
    cv::resize(srcMat, srcMat, cv::Size(width, height));

    cv::String windowName = _windowTitle.toStdString();
    cvui::init(windowName);

    if(!srcMat.data)
    {
        qDebug() << __FILE__ << __LINE__
                 << "Failed to load image:" << fileName1;
        return;
    }

    qDebug() << __FILE__ << __LINE__
             << "Succeed to load image, type =" << srcMat.type()
             << "channels = " << srcMat.channels();

    cv::Mat dstMat;
    dstMat = cv::Mat::zeros(srcMat.size(), srcMat.type());
    cv::Mat windowMat = cv::Mat(cv::Size(dstMat.cols * 3, dstMat.rows * 2),
                                srcMat.type());

    int minThresh = 100;
    int maxThresh = 200;
    int maxVal = 255;

    while(true)
    {
        windowMat = cv::Scalar(0, 0, 0);
        // 原圖先copy到左邊
        cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows),
                                    cv::Range(0, srcMat.cols));
        cv::addWeighted(leftMat, 1.0f, srcMat, 1.0f, 0.0f, leftMat);

        // 調整閾值化的參數thresh
        cvui::printf(windowMat, width * 2 + 50, 0 + height * 0, "minThresh");
        cvui::trackbar(windowMat, width * 2 + 50, 15 + height * 0, 200, &minThresh, 0, 255);

        // 調整閾值化的參數thresh
        cvui::printf(windowMat, width * 2 + 50, 60 + height * 0, "maxThresh");
        cvui::trackbar(windowMat, width * 2 + 50, 75 + height * 0, 200, &maxThresh, 0, 255);

        // 調整閾值化的參數maxval
        cvui::printf(windowMat, width * 2 + 50, 120 + height * 0, "maxVal");
        cvui::trackbar(windowMat, width * 2 + 50, 135 + height * 0, 200, &maxVal, 0, 255);

        // 轉換成灰度圖像
        cv::Mat grayMat;    // 多通道
        cv::Mat grayMat2;   // 單通道
#if 1
        // CV_XXXX 與 cv::COLOR_BGR2GRAY 實際並無區別 是高低版本表現形式的問題
        cv::cvtColor(srcMat, grayMat2, CV_BGR2GRAY);
        cv::cvtColor(grayMat2, grayMat, CV_GRAY2BGR);
#else
        cv::cvtColor(srcMat, grayMat2, cv::COLOR_BGR2GRAY);
        cv::cvtColor(grayMat2, grayMat, cv::COLOR_GRAY2BGR);
#endif
        // 效果圖copy
        cv::Mat rightMat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
                                     cv::Range(srcMat.cols * 1, srcMat.cols * 2));
        cv::addWeighted(rightMat, 0.0f, grayMat, 1.0f, 0.0f, rightMat);

        {
            cv::Mat threadMatMin;
            cv::Mat threadMatMax;
            cv::Mat threadMatMin2;
            cv::Mat threadMatMax2;
            // 最小值的閾值化:低於最大值得置0,高於最小值的爲255
            cv::threshold(grayMat2, 
                          threadMatMin,
                          minThresh, 
                          maxVal, 
                          cv::THRESH_BINARY);
            // 單通道轉爲3通道(窗口爲3通道的mat)
            cv::cvtColor(threadMatMin, threadMatMin2, CV_GRAY2BGR);
            // 效果圖copy
            cv::Mat mat1 = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                                       cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::addWeighted(mat1, 0.0f, threadMatMin2, 1.0f, 0.0f, mat1);

            // 最大值的閾值化: 大於最大值的反倒置0,低於最大值的爲255
            cv::threshold(grayMat2,
                          threadMatMax, 
                          maxThresh, 
                          maxVal, 
                          cv::THRESH_BINARY_INV);
            // 單通道轉爲3通道(窗口爲3通道的mat)
            cv::cvtColor(threadMatMax, threadMatMax2, CV_GRAY2BGR);
            // 效果圖copy
            cv::Mat mat2 = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                                       cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::addWeighted(mat2, 0.0f, threadMatMax2, 1.0f, 0.0f, mat2);

            // 而後將二者進行與計算
            cv::bitwise_and(threadMatMin, threadMatMax, dstMat);
            // 單通道轉爲3通道(窗口爲3通道的mat)
            cv::cvtColor(dstMat, dstMat, CV_GRAY2BGR);
            // 效果圖copy
            cv::Mat center = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                                       cv::Range(srcMat.cols * 2, srcMat.cols * 3));
            cv::addWeighted(center, 0.0f, dstMat, 1.0f, 0.0f, center);
        }

        // 更新
        cvui::update();
        // 顯示
        cv::imshow(windowName, windowMat);
        // esc鍵退出
        if(cv::waitKey(25) == 27)
        {
            break;
        }
    }
}

 

工程模板:對應版本號v1.26.0

       對應版本號v1.26.0blog

 

上一篇:OpenCV開發筆記(三十):帶你學習圖像識別之經典OTSU算法閾值化

下一篇:OpenCV開發筆記(三十二):紅胖子8分鐘帶你深刻了解半閾值化(圖文並貌+淺顯易懂+程序源碼)


原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/104858803

本文同步分享在 博客「紅胖子(AAA紅模仿)」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索