openCV實(shí)現(xiàn)圖像分割
本次實(shí)驗(yàn)為大家分享了openCV實(shí)現(xiàn)圖像分割的具體實(shí)現(xiàn)代碼,供大家參考,具體內(nèi)容如下
一.實(shí)驗(yàn)?zāi)康?/h3>
進(jìn)一步理解圖像的閾值分割方法和邊緣檢測(cè)方法的原理。
掌握?qǐng)D像基本全局閾值方法和最大類(lèi)間方差法(otsu法)的原理并編程實(shí)現(xiàn)。
編程實(shí)現(xiàn)圖像的邊緣檢測(cè)。
二.實(shí)驗(yàn)內(nèi)容和要求
編程實(shí)現(xiàn)圖像閾值分割(基本全局閾值方法和otsu法)和邊緣檢測(cè)。
三.實(shí)驗(yàn)主要儀器設(shè)備和材料
計(jì)算機(jī),VS2017+OpenCV
四.實(shí)驗(yàn)原理與方法
圖像的閾值分割的基本原理
圖像的二值化處理圖像分割中的一個(gè)主要內(nèi)容,就是將圖像上的點(diǎn)的灰度置為0或255,也就是講整個(gè)圖像呈現(xiàn)出明顯的黑白效果。用I表示原圖,R表示二值化后的圖,則二值化的過(guò)程可以用以下公式表示:
thr表示選取的閾值。二值化的過(guò)程就是當(dāng)原圖的像素灰度值大于閾值就將其變白,否則就將其變黑。即將256個(gè)亮度等級(jí)的灰度圖像通過(guò)適當(dāng)?shù)拈y值選取而將圖像變?yōu)槎€(gè)級(jí)別灰度級(jí),這樣只有二個(gè)灰度級(jí)的圖像在圖像處理分析過(guò)程中占有非常重要的地位,特別是在實(shí)用的圖像處理中。
根據(jù)對(duì)全圖使用統(tǒng)一閾值還是對(duì)不同區(qū)域使用不同閾值,可以分為全局閾值方法(global thresholding)和局部閾值方法(local thresholding,也叫做自適應(yīng)閾值方法adaptive thresholding);這種與坐標(biāo)相關(guān)的閾值也叫動(dòng)態(tài)閾值,具體的方法,可以參考相關(guān)的圖像處理書(shū)籍。
1、基本全局閾值方法,即在整個(gè)圖像中所有的象素點(diǎn),其閾值thr相同,具體步驟為:
(1)選取一個(gè)初始估計(jì)值T;
(2)用T分割圖像。這樣便會(huì)生成兩組像素集合:G1由所有灰度值大于T的像素組成,而G2由所有灰度值小于或等于T的像素組成。
(3)對(duì)G1和G2中所有像素計(jì)算平均灰度值u1和u2。
(4)計(jì)算新的閾值:T=(u1 + u2)/2。
(5)重復(fù)步驟(2)到(4),直到得到的T值之差小于一個(gè)事先定義的參數(shù)T0。
2、Otsu方法的算法步驟為:
(1)先計(jì)算圖像的歸一化直方圖;
(2)i表示分類(lèi)的閾值,也即一個(gè)灰度級(jí),從0開(kāi)始迭代;
(3)通過(guò)歸一化的直方圖,統(tǒng)計(jì)0~i 灰度級(jí)的像素(背景像素) 所占整幅圖像的比例w0,并統(tǒng)計(jì)背景像素的平均灰度u0;統(tǒng)計(jì)i~255灰度級(jí)的像素(前景像素) 所占整幅圖像的比例w1,并統(tǒng)計(jì)前景像素的平均灰度u1;
(4)計(jì)算前景像素和背景像素的方差 g = w0w1(u0-u1) (u0-u1)
(5)i++,直到i為256時(shí)結(jié)束迭代;
(6)將最大g相應(yīng)的i值作為圖像的全局閾值。
邊緣檢測(cè)
圖像中邊緣的檢測(cè)可以借助一階和二階微分實(shí)現(xiàn),常見(jiàn)的一階邊緣檢測(cè)算子包括Roberts算子、Prewitt算子和Sobel算子,二階算子主要是Laplacian算子,由于受噪聲影響比較大,往往在使用之前先對(duì)圖像進(jìn)行平滑處理,LOG算子就是先對(duì)圖像進(jìn)行高斯平滑,然后進(jìn)行拉普拉斯變換并求零交叉點(diǎn)。Canny算子是最優(yōu)的邊緣檢測(cè)算子。
五.實(shí)驗(yàn)內(nèi)容
1、圖像的閾值分割:
圖像為車(chē)牌圖像,編寫(xiě)代碼實(shí)現(xiàn)基本全局閾值法和Otsu法,比較分割結(jié)果。
2、邊緣檢測(cè)
用邊緣檢測(cè)算子對(duì)車(chē)牌圖像進(jìn)行處理,可以用梯度算子、Laplacian算子或Canny算子(Canny算子可以直接用OpenCV函數(shù))。比較先閾值分割后邊緣檢測(cè)和直接對(duì)圖像進(jìn)行邊緣檢測(cè)這兩種情況的結(jié)果是否有差別。
注意:這里提取灰度邊緣即可。
代碼:
#include "pch.h" #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; // 拉普拉斯銳化函數(shù) void LaplacianSharpDeal(const Mat &src, Mat &dst) { if (!src.data)return; for (int i = 0; i < src.rows; ++i) for (int j = 0; j < src.cols; ++j) { float a; if (i > 1 && i < src.rows - 1 && j > 1 && j < src.cols - 1) { a = 5 * (float)src.at<uchar>(i, j) - (float)src.at<uchar>(i - 1, j) - (float)src.at<uchar>(i, j - 1) - (float)src.at<uchar>(i, j + 1) - (float)src.at<uchar>(i + 1, j); } else {//邊緣賦值 a = src.at<uchar>(i, j); } if (a > 255 || a < 0) { dst.at<uchar>(i, j) = src.at<uchar>(i, j); } else { dst.at<uchar>(i, j) = a; } } } // 基本全局閾值方法函數(shù) int BasicGlobalThreshold(Mat src, float oldValue) { int cols = src.cols; int rows = src.rows; float G1 = 0; float G2 = 0; float g1 = 0; float g2 = 0; float u1 = 0; float u2 = 0; float T0 = 0; // 計(jì)算灰度直方圖分布,統(tǒng)計(jì)像素?cái)?shù)和頻率 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (src.at<uchar>(i, j) > oldValue) { G1 += src.at<uchar>(i, j); g1 += 1; } else { G2 += src.at<uchar>(i, j); g2 += 1; } } } u1 = G1 / g1; u2 = G2 / g2; T0 = (u1 + u2) / 2; std::cout << T0 << std::endl; if (abs(oldValue - T0) < 0.1) { return T0; } else { BasicGlobalThreshold(src, T0); } } // Otsu方法函數(shù) int Otsu(Mat src) { int cols = src.cols; int rows = src.rows; int nPixelNum = cols * rows; // 初始化 int pixelNum[256]; double probability[256]; for (int i = 0; i < 256; i++) { pixelNum[i] = 0; probability[i] = 0.0; } // 統(tǒng)計(jì)像素?cái)?shù)和頻率 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { pixelNum[src.at<uchar>(i, j)]++; } } for (int i = 0; i < 256; i++) { probability[i] = (double)0.1*pixelNum[i] / nPixelNum; } // 計(jì)算 int Threshold = 0; // 最佳閾值 double MaxDelta = 0.0; // 最大類(lèi)間方差 double Mean_0 = 0.0; // 左邊平均值 double Mean_1 = 0.0; // 右邊平均值 double Delta = 0.0; // 類(lèi)間方差 double Mean_0_temp = 0.0; // 左邊平均值中間值 double Mean_1_temp = 0.0; // 右邊平均值中間值 double Probability_0 = 0.0; // 左邊頻率值 double Probability_1 = 0.0; // 右邊頻率值 for (int j = 0; j < 256; j++) { for (int i = 0; i < 256; i++) { if (i < j)// 前半部分 { Probability_0 += probability[i]; Mean_0_temp += i * probability[i]; } else // 后半部分 { Probability_1 += probability[i]; Mean_1_temp += i * probability[i]; } } // 計(jì)算平均值 // Mean_0_teamp計(jì)算的是前半部分的灰度值的總和除以總像素?cái)?shù), // 所以要除以前半部分的頻率才是前半部分的平均值,后半部分同樣 Mean_0 = Mean_0_temp / Probability_0; Mean_1 = Mean_1_temp / Probability_1; Delta = (double)(Probability_0 * Probability_1 * pow((Mean_0 - Mean_1), 2)); if (Delta > MaxDelta) { MaxDelta = Delta; Threshold = j; } // 相關(guān)參數(shù)歸零 Probability_0 = 0.0; Probability_1 = 0.0; Mean_0_temp = 0.0; Mean_1_temp = 0.0; Mean_0 = 0.0; Mean_1 = 0.0; Delta = 0.0; } return Threshold; } void main() { Mat image = imread("A1.bmp", 0); Mat image1,image2; Mat image3(image.size(), image.type()); Mat image4(image.size(), image.type()); std::cout << "基本全局閾值方法" << std::endl; int OstuThreshold1 = BasicGlobalThreshold(image, 0.01); int OstuThreshold2 = Otsu(image); std::cout << "Otsu方法" << std::endl; std::cout << OstuThreshold2 << std::endl; threshold(image, image1, OstuThreshold1, 255, CV_THRESH_OTSU); threshold(image, image2, OstuThreshold2, 255, CV_THRESH_OTSU); LaplacianSharpDeal(image2, image3); LaplacianSharpDeal(image, image4); imshow("基本全局閾值方法", image1); imshow("Otsu方法", image2); imshow("先閾值分割后邊緣檢測(cè)", image3); imshow("直接對(duì)圖像進(jìn)行邊緣檢測(cè)", image4); waitKey(); }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)支持動(dòng)態(tài)拓展和銷(xiāo)毀的線程池
這篇文章主要為大家介紹了C語(yǔ)言實(shí)現(xiàn)支持動(dòng)態(tài)拓展和銷(xiāo)毀的線程池,感興趣的小伙伴們可以參考一下2016-01-01C++基于socket UDP網(wǎng)絡(luò)編程實(shí)現(xiàn)簡(jiǎn)單聊天室功能
這篇文章主要為大家詳細(xì)介紹了C++基于socket UDP網(wǎng)絡(luò)編程實(shí)現(xiàn)簡(jiǎn)單聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07C語(yǔ)言二進(jìn)制思想以及數(shù)據(jù)的存儲(chǔ)
本文主要介紹了C語(yǔ)言的二進(jìn)制思想以及數(shù)據(jù)的存儲(chǔ),這里對(duì)二進(jìn)制和數(shù)據(jù)存儲(chǔ)做了詳細(xì)的說(shuō)明,對(duì)開(kāi)始學(xué)習(xí)C語(yǔ)言的同學(xué)比較有參考價(jià)值2016-07-07C語(yǔ)言實(shí)現(xiàn)停車(chē)場(chǎng)項(xiàng)目
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)停車(chē)場(chǎng)項(xiàng)目,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03詳解C++設(shè)計(jì)模式編程中對(duì)訪問(wèn)者模式的運(yùn)用
這篇文章主要介紹了C++設(shè)計(jì)模式編程中對(duì)訪問(wèn)者模式的運(yùn)用,訪問(wèn)者模式在不破壞類(lèi)的前提下為類(lèi)提供增加新的新操作,需要的朋友可以參考下2016-03-03C/C++惡意代碼盤(pán)點(diǎn)之文件自動(dòng)刪除
惡意代碼的分類(lèi)包括計(jì)算機(jī)病毒、蠕蟲(chóng)、木馬等,有些技術(shù)經(jīng)常用到,有的也是必然用到。今天我們就分享一下文件自動(dòng)刪除,感興趣的可以了解一下2022-09-09C語(yǔ)言實(shí)現(xiàn)旅游景點(diǎn)咨詢(xún)系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)旅游景點(diǎn)咨詢(xún)系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12C/C++實(shí)現(xiàn)個(gè)人收支系統(tǒng)的示例代碼
這篇文章主要介紹了C/C++實(shí)現(xiàn)個(gè)人收支系統(tǒng),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06