日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

opencv自适应二值化的应用

發布時間:2023/12/14 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opencv自适应二值化的应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

opencv自適應二值化

  • 前言
  • 一、二值化是什么?
  • 二、自適應二值化
    • 1.為什么要用自適應二值化
    • 2.自適應二值化代碼實現(c++)


前言

最近在工作中,要實現自動繪制ROI的功能,但是在代碼實現的過程中,遇到了不小的問題,現已解決。


一、二值化是什么?

圖像的二值化,就是將圖像上的像素點的灰度值設置為0或255,也就是將整個圖像呈現出明顯的只有黑和白的視覺效果。
二值化是圖像分割的一種最簡單的方法。二值化可以把灰度圖像轉換成二值圖像。把大于某個臨界灰度值的像素灰度設為灰度極大值,把小于這個值的像素灰度設為灰度極小值,從而實現二值化。
根據閾值選取的不同,二值化的算法分為固定閾值和自適應閾值。

二、自適應二值化

1.為什么要用自適應二值化

在處理從一個視頻流中獲取的圖片時,往往因為光線的變化,而導致固定的閾值不適用,這樣就會導致圖片處理的結果大打折扣,現做如下比較:
原圖_1:

在圖中我們可以看到,只有這個水杯我們希望是黑色的,背景應該處理成白色。那么進行如下不同閾值的嘗試。
閾值_100:

cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 100, 255, CV_THRESH_BINARY);cv::imwrite("D:/閾值_100.jpg", srcClone);


閾值_110:

cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 110, 255, CV_THRESH_BINARY);cv::imwrite("D:/閾值_110.jpg", srcClone);

閾值_120:

cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 120, 255, CV_THRESH_BINARY);cv::imwrite("D:/閾值_120.jpg", srcClone);


還是同樣的環境(拍攝角度改變了,但還是這個水杯),改變亮度,再來看這個水杯:
原圖_2:

閾值_50:

cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 50, 255, CV_THRESH_BINARY);cv::imwrite("D:/閾值_50.jpg", srcClone);

閾值_100:

cvtColor(srcClone, srcClone, CV_BGR2GRAY);threshold(srcClone, srcClone, 100, 255, CV_THRESH_BINARY);cv::imwrite("D:/閾值_100.jpg", srcClone);

很明顯可以看到,對于亮度改變的原圖_2,原先的閾值_100已經不能完全適用,如果將閾值提升到110甚至再往上就會出現大面積黑色的結果,這就是要使用自適應二值化的原因,可以明顯降低亮度變化帶來的影響(當然不僅僅用于處理亮度變化)。
接下來看看自適應二值化的結果:
原圖_1的自適應二值化:

原圖_2的自適應二值化:

從以上結果我們可以看出,對于不同亮度的圖片,使用自適應二值化后的結果是相差不大的,但是將兩種不同的二值化結果相比較可得出,當背景沒有過多的影子以及整張圖的亮度沒有明顯變化(比如從左到右變暗)時,自適應二值化后的結果不一定比得過參數調好的固定閾值二值化,這是因為背景光源信息過于簡單(大智若愚),但在處理視頻流信息的時候,背景光源總會發生不可控的變化,我們肯定不能每次都通過人工來調整閾值,這是不符合自動化工藝的,因此就要使用一個比較好的自適應二值化。
再給出一個例子:

自適應二值化結果:

在這里就不浪費篇幅與固定閾值二值化做比較,讀者可自行比較(本人已經試過,效果沒那么好)。

2.自適應二值化代碼實現(c++)

void thresholdIntegral(cv::Mat &inputMat, cv::Mat &outputMat) {// accept only char type matricesCV_Assert(!inputMat.empty());CV_Assert(inputMat.depth() == CV_8U);CV_Assert(inputMat.channels() == 1);CV_Assert(!outputMat.empty());CV_Assert(outputMat.depth() == CV_8U);CV_Assert(outputMat.channels() == 1);// rows -> height -> yint nRows = inputMat.rows;// cols -> width -> xint nCols = inputMat.cols;// create the integral imagecv::Mat sumMat;cv::integral(inputMat, sumMat);CV_Assert(sumMat.depth() == CV_32S);CV_Assert(sizeof(int) == 4);int S = MAX(nRows, nCols)/8;double T = 0.15;// perform thresholdingint s2 = S/2;int x1, y1, x2, y2, count, sum;// CV_Assert(sizeof(int) == 4);int *p_y1, *p_y2;uchar *p_inputMat, *p_outputMat;for( int i = 0; i < nRows; ++i){y1 = i-s2;y2 = i+s2;if (y1 < 0){y1 = 0;}if (y2 >= nRows) {y2 = nRows-1;}p_y1 = sumMat.ptr<int>(y1);p_y2 = sumMat.ptr<int>(y2);p_inputMat = inputMat.ptr<uchar>(i);p_outputMat = outputMat.ptr<uchar>(i);for ( int j = 0; j < nCols; ++j){// set the SxS regionx1 = j-s2;x2 = j+s2;if (x1 < 0) {x1 = 0;}if (x2 >= nCols) {x2 = nCols-1;}count = (x2-x1)*(y2-y1);// I(x,y)=s(x2,y2)-s(x1,y2)-s(x2,y1)+s(x1,x1)sum = p_y2[x2] - p_y1[x2] - p_y2[x1] + p_y1[x1];if ((int)(p_inputMat[j] * count) < (int)(sum*(1.0-T)))p_outputMat[j] = 255;elsep_outputMat[j] = 0;}} } --- 參考自:[添加鏈接描述](https://www.cnblogs.com/polly333/p/7269153.html) 這套算法以W*W為模板的矩形區域的二維平滑值來代替一維加權值,從而拋開了一維平滑的方向性問題,是Wellner 自適應濾波閾值的升級版。 若有人對算法原理感興趣或對源碼中有不理解的部分可移步下一篇博客,其中會根據自己的理解進行詳細介紹。 本文如有問題請積極指出,萬分感謝。

總結

以上是生活随笔為你收集整理的opencv自适应二值化的应用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。