新聞中心
使用OPENCV,編寫代碼,學(xué)習(xí)圖像二值化算法,以及邊緣檢測算法,進(jìn)行圖像的分割。
下面主要介紹Robert算子的實(shí)現(xiàn)過程:
①任務(wù)分析調(diào)入并顯示圖像;使用Roberts 算子對圖像進(jìn)行邊緣檢測處理; Roberts 算子為一對模板:
相應(yīng)的矩陣為:rh = [0 1;-1 0];?rv = [1 0;0 -1];這里的rh 為水平Roberts 算子,rv為垂直Roberts 算子。分別顯示處理后的水平邊界和垂直邊界檢測結(jié)果;用“歐幾里德距離”和“街區(qū)距離”方式計(jì)算梯度的模,并顯示檢測結(jié)果;對于檢測結(jié)果進(jìn)行二值化處理,并顯示處理結(jié)果。
②代碼實(shí)現(xiàn)先加載需要的庫
#include#includeusing namespace cv;
接著定義一個(gè)基于Roberts算子實(shí)現(xiàn)閾值分割的函數(shù),其功能包括顯示用街區(qū)距離和歐幾里得距離得出的梯度圖、選擇一個(gè)合適的閾值實(shí)現(xiàn)圖像分割。
其中街區(qū)距離就是水平梯度和垂直梯度的和:
Robert_City.at(row, col) = saturate_cast(fabs(img.at(row, col) - img.at(row + 1, col + 1))+ fabs(img.at(row, col + 1) - img.at(row + 1, col)));
saturate_cast
而歐幾里得距離就是水平梯度和垂直梯度的平方和再開方:
Robert_Ojld.at(row, col) = saturate_cast(sqrt(pow(img.at(row, col) - img.at(row + 1, col + 1),2) + pow(img.at(row, col + 1) - img.at(row + 1, col),2)));
具體代碼實(shí)現(xiàn):
Mat Robert_City = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算城市距離的空白圖像
Mat Robert_Ojld = Mat::zeros(Size(img.rows, img.cols), img.type()); //用于計(jì)算歐幾里得距離的空白圖像
for (int row = 0; row< img.rows-1; row++) {
for (int col = 0; col< img.cols-1; col++) { // 由于像素之間的加減可能會小于零,因此記得加上絕對值函數(shù)fabs()
Robert_City.at(row, col) = saturate_cast(fabs(img.at(row, col) - img.at(row + 1, col + 1)) + fabs(img.at(row, col + 1) - img.at(row + 1, col)));
}
}
for (int row = 0; row< img.rows - 1; row++) {
for (int col = 0; col< img.cols - 1; col++) {
Robert_Ojld.at(row, col) = saturate_cast(sqrt(pow(img.at(row, col) - img.at(row + 1, col + 1),2) + pow(img.at(row, col + 1) - img.at(row + 1, col),2)));
}
}
imshow("Robert圖像(街區(qū)距離)", Robert_City);
imshow("Robert圖像(歐幾里得距離)", Robert_Ojld);
結(jié)果如下:
(原圖)
接下來要選擇一個(gè)合適的閾值用于圖像的二值化。選擇閾值的方式有很多暴力遍歷(不推薦)、調(diào)用函數(shù)法(直接輸出直方圖看每一個(gè)像素值的數(shù)量,方便主觀判斷)和數(shù)組法。這里介紹一下數(shù)組法:創(chuàng)建一個(gè)256大小的一維數(shù)組arr[256],每一個(gè)元素依據(jù)索引代表對應(yīng)的像素值的個(gè)數(shù)。就比如說假設(shè)一共有10000個(gè)點(diǎn)像素值為0,那么arr[0] = 10000。先對歐幾里得距離實(shí)現(xiàn)二值化,實(shí)現(xiàn)如下:
int pixel_num[256] = {0}; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows ; row++) {
for (int col = 0; col< img.cols ; col++) {
pixel_num[Robert_Ojld.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int times = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<<"像素值"<
輸出結(jié)果:
可以看出,像素值9和像素值10差異變化較大。因此可以選擇像素值10作為分割圖像的閾值,比像素值10小的像素全部賦值為0,比像素值大的全部賦值255:
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Robert_Ojld.at(row, col)< 10) {
Robert_Ojld.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Robert_Ojld.at(row, col) = 255;
}
}
}
imshow("歐幾里得閾值分割", Robert_Ojld);
可以看到閾值分割效果不錯(cuò),但是不足之處也很明顯:圖像因此留下了很多離散點(diǎn),這是閾值選擇得不夠大的原因。于是我又偷偷的把閾值調(diào)整為15:在保證圖片不失真的情況下,15作為閾值要明顯好于10。
同理,街區(qū)距離的做法和歐幾里得距離類似,也是通過數(shù)組得到較為可信的閾值之后再細(xì)微調(diào)整。
街區(qū)距離的實(shí)現(xiàn)過程以及結(jié)果如下所示:
int pixel_num02[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Robert_City.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int time = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< time<< "的數(shù)目為: "<< pixel_num02[time]<< endl; // 遍歷輸出
time++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Robert_City.at(row, col)< 20) {
Robert_City.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Robert_City.at(row, col) = 255;
}
}
}
imshow("街區(qū)距離閾值分割", Robert_City);
注意:閾值的選擇是很關(guān)鍵的,如果閾值選擇過大的話可能會導(dǎo)致邊緣斷開的情況,也就是失真。這就需要我們在去噪和失真兩個(gè)方面做權(quán)衡。以下給出了基于Roberts算子的閾值分割函數(shù)的完整代碼:
void Roberts(Mat& img) { // 基于Roberts算子的閾值分割
Mat Robert_City = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算城市距離的空白圖像
Mat Robert_Ojld = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算歐幾里得距離的空白圖像
for (int row = 0; row< img.rows-1; row++) {
for (int col = 0; col< img.cols-1; col++) { // 由于像素之間的加減可能會小于零,因此記得加上絕對值函數(shù)fabs()
Robert_City.at(row, col) = saturate_cast(fabs(img.at(row, col) - img.at(row + 1, col + 1)) + fabs(img.at(row, col + 1) - img.at(row + 1, col)));
}
}
for (int row = 0; row< img.rows - 1; row++) {
for (int col = 0; col< img.cols - 1; col++) {
Robert_Ojld.at(row, col) = saturate_cast(sqrt(pow(img.at(row, col) - img.at(row + 1, col + 1),2) + pow(img.at(row, col + 1) - img.at(row + 1, col),2)));
}
}
imshow("Robert圖像(街區(qū)距離)", Robert_City);
imshow("Robert圖像(歐幾里得距離)", Robert_Ojld);
int pixel_num01[256] = {0}; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows ; row++) {
for (int col = 0; col< img.cols ; col++) {
pixel_num01[Robert_Ojld.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int times = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<<"像素值"<(row, col)< 15) {
Robert_Ojld.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Robert_Ojld.at(row, col) = 255;
}
}
}
imshow("歐幾里得閾值分割", Robert_Ojld);
int pixel_num02[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Robert_City.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int time = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< time<< "的數(shù)目為: "<< pixel_num02[time]<< endl; // 遍歷輸出
time++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Robert_City.at(row, col)< 20) {
Robert_City.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Robert_City.at(row, col) = 255;
}
}
}
imshow("街區(qū)距離閾值分割", Robert_City);
waitKey(0);
destroyAllWindows();
}
類似的如Prewitt算子、Sobel算子與上述的Roberts算子類似,其閾值分割的過程都是先用街區(qū)距離、歐幾里得距離分別算出原始圖像的梯度,然后再創(chuàng)建一個(gè)一維數(shù)組來記錄下每個(gè)像素值的數(shù)目以備接下來的閾值選擇操作。最后的閾值選擇既需要能有效地對圖像進(jìn)行分割,也要保證圖像不會出現(xiàn)失真的現(xiàn)象。
以下分別是基于Prewitt算子的閾值分割函數(shù)、基于Sobel算子的閾值分割函數(shù)。
void Prewitt(Mat& img) { // 基于Prewitt算子的閾值分割
Mat Prewitt_City = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算城市距離的空白圖像
Mat Prewitt_Ojld = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算歐幾里得距離的空白圖像
for (int row = 1; row< img.rows - 1; row++) {
for (int col = 1; col< img.cols - 1; col++) { // 由于像素之間的加減可能會小于零,因此記得加上絕對值函數(shù)fabs()
Prewitt_City.at(row, col) = saturate_cast(fabs(img.at(row-1, col+1) - img.at(row - 1, col - 1)+ img.at(row , col + 1)- img.at(row, col - 1)+ img.at(row + 1, col + 1)- img.at(row + 1, col - 1)) + fabs(img.at(row+1, col - 1) - img.at(row -1 , col-1)+ img.at(row + 1, col)- img.at(row - 1, col)+ img.at(row + 1, col + 1)- img.at(row - 1, col + 1)));
}
}
for (int row = 1; row< img.rows - 1; row++) {
for (int col = 1; col< img.cols - 1; col++) {
Prewitt_Ojld.at(row, col) = saturate_cast(sqrt(pow(img.at(row - 1, col + 1) - img.at(row - 1, col - 1) + img.at(row, col + 1) - img.at(row, col - 1)+ img.at(row + 1, col + 1) - img.at(row + 1, col - 1), 2) + pow(img.at(row + 1, col - 1) - img.at(row - 1, col - 1) + img.at(row + 1, col) - img.at(row - 1, col) + img.at(row + 1, col + 1) - img.at(row - 1, col + 1), 2)));
}
}
imshow("Prewitt圖像(街區(qū)距離)", Prewitt_City);
imshow("Prewitt圖像(歐幾里得距離)", Prewitt_Ojld);
int pixel_num01[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Prewitt_Ojld.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int times = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< times<< "的數(shù)目為: "<< pixel_num01[times]<< endl; // 遍歷輸出
times++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Prewitt_Ojld.at(row, col)< 70) {
Prewitt_Ojld.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Prewitt_Ojld.at(row, col) = 255;
}
}
}
imshow("歐幾里得閾值分割", Prewitt_Ojld);
int pixel_num02[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Prewitt_City.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int time = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< time<< "的數(shù)目為: "<< pixel_num02[time]<< endl; // 遍歷輸出
time++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Prewitt_City.at(row, col)< 70) {
Prewitt_City.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Prewitt_City.at(row, col) = 255;
}
}
}
imshow("街區(qū)距離閾值分割", Prewitt_City);
waitKey(0);
destroyAllWindows();
}
void Sobel(Mat& img) { // 基于Prewitt算子的閾值分割
Mat Sobel_City = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算城市距離的空白圖像
Mat Sobel_Ojld = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算歐幾里得距離的空白圖像
for (int row = 1; row< img.rows - 1; row++) {
for (int col = 1; col< img.cols - 1; col++) { // 由于像素之間的加減可能會小于零,因此記得加上絕對值函數(shù)fabs()
Sobel_City.at(row, col) = saturate_cast(fabs(img.at(row - 1, col + 1) - img.at(row - 1, col - 1) + 2*img.at(row, col + 1) - 2*img.at(row, col - 1) + img.at(row + 1, col + 1) - img.at(row + 1, col - 1)) + fabs(img.at(row + 1, col - 1) - img.at(row - 1, col - 1) + 2*img.at(row + 1, col) - 2*img.at(row - 1, col) + img.at(row + 1, col + 1) - img.at(row - 1, col + 1)));
}
}
for (int row = 1; row< img.rows - 1; row++) {
for (int col = 1; col< img.cols - 1; col++) {
Sobel_Ojld.at(row, col) = saturate_cast(sqrt(pow(img.at(row - 1, col + 1) - img.at(row - 1, col - 1) + 2*img.at(row, col + 1) - 2*img.at(row, col - 1) + img.at(row + 1, col + 1) - img.at(row + 1, col - 1), 2) + pow(img.at(row + 1, col - 1) - img.at(row - 1, col - 1) + 2*img.at(row + 1, col) - 2*img.at(row - 1, col) + img.at(row + 1, col + 1) - img.at(row - 1, col + 1), 2)));
}
}
imshow("Sobel圖像(街區(qū)距離)", Sobel_City);
imshow("Sobel圖像(歐幾里得距離)", Sobel_Ojld);
int pixel_num01[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Sobel_Ojld.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int times = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< times<< "的數(shù)目為: "<< pixel_num01[times]<< endl; // 遍歷輸出
times++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Sobel_Ojld.at(row, col)< 70) {
Sobel_Ojld.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Sobel_Ojld.at(row, col) = 255;
}
}
}
imshow("歐幾里得閾值分割", Sobel_Ojld);
int pixel_num02[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Sobel_City.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int time = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< time<< "的數(shù)目為: "<< pixel_num02[time]<< endl; // 遍歷輸出
time++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Sobel_City.at(row, col)< 70) {
Sobel_City.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Sobel_City.at(row, col) = 255;
}
}
}
imshow("街區(qū)距離閾值分割", Sobel_City);
waitKey(0);
destroyAllWindows();
}
Prewitt算子和Sobel算子大同小異,Sobel是在Prewitt的基礎(chǔ)上增加了權(quán)重,也就是越靠近當(dāng)前像素值,那么它所發(fā)揮的作用就越大??傮w而言的話Prewitt算子和Sobel算子的結(jié)果會比Roberts算子的結(jié)果要好一些,下面是基于兩者的閾值分割結(jié)果:
總代碼如下:
#include#include#includeusing namespace cv;
using namespace std;
void Roberts(Mat& img);
void Prewitt(Mat& img);
void Sobel(Mat& img);
int main() {
Mat Gray = imread("C:\\Users\\Czhannb\\Desktop\\gray.png", IMREAD_GRAYSCALE);
if (Gray.empty()) {
cout<< "讀取圖片錯(cuò)誤!"<< endl;
}
else {
imshow("未動工之前:", Gray);
}
//Roberts(Gray);
//Prewitt(Gray);
Sobel(Gray);
return 0;
}
void Roberts(Mat& img) { // 基于Roberts算子的閾值分割
Mat Robert_City = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算城市距離的空白圖像
Mat Robert_Ojld = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算歐幾里得距離的空白圖像
for (int row = 0; row< img.rows-1; row++) {
for (int col = 0; col< img.cols-1; col++) { // 由于像素之間的加減可能會小于零,因此記得加上絕對值函數(shù)fabs()
Robert_City.at(row, col) = saturate_cast(fabs(img.at(row, col) - img.at(row + 1, col + 1)) + fabs(img.at(row, col + 1) - img.at(row + 1, col)));
}
}
for (int row = 0; row< img.rows - 1; row++) {
for (int col = 0; col< img.cols - 1; col++) {
Robert_Ojld.at(row, col) = saturate_cast(sqrt(pow(img.at(row, col) - img.at(row + 1, col + 1),2) + pow(img.at(row, col + 1) - img.at(row + 1, col),2)));
}
}
imshow("Robert圖像(街區(qū)距離)", Robert_City);
imshow("Robert圖像(歐幾里得距離)", Robert_Ojld);
int pixel_num01[256] = {0}; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows ; row++) {
for (int col = 0; col< img.cols ; col++) {
pixel_num01[Robert_Ojld.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int times = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<<"像素值"<(row, col)< 15) {
Robert_Ojld.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Robert_Ojld.at(row, col) = 255;
}
}
}
imshow("歐幾里得閾值分割", Robert_Ojld);
int pixel_num02[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Robert_City.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int time = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< time<< "的數(shù)目為: "<< pixel_num02[time]<< endl; // 遍歷輸出
time++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Robert_City.at(row, col)< 20) {
Robert_City.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Robert_City.at(row, col) = 255;
}
}
}
imshow("街區(qū)距離閾值分割", Robert_City);
waitKey(0);
destroyAllWindows();
}
void Prewitt(Mat& img) { // 基于Prewitt算子的閾值分割
Mat Prewitt_City = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算城市距離的空白圖像
Mat Prewitt_Ojld = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算歐幾里得距離的空白圖像
for (int row = 1; row< img.rows - 1; row++) {
for (int col = 1; col< img.cols - 1; col++) { // 由于像素之間的加減可能會小于零,因此記得加上絕對值函數(shù)fabs()
Prewitt_City.at(row, col) = saturate_cast(fabs(img.at(row-1, col+1) - img.at(row - 1, col - 1)+ img.at(row , col + 1)- img.at(row, col - 1)+ img.at(row + 1, col + 1)- img.at(row + 1, col - 1)) + fabs(img.at(row+1, col - 1) - img.at(row -1 , col-1)+ img.at(row + 1, col)- img.at(row - 1, col)+ img.at(row + 1, col + 1)- img.at(row - 1, col + 1)));
}
}
for (int row = 1; row< img.rows - 1; row++) {
for (int col = 1; col< img.cols - 1; col++) {
Prewitt_Ojld.at(row, col) = saturate_cast(sqrt(pow(img.at(row - 1, col + 1) - img.at(row - 1, col - 1) + img.at(row, col + 1) - img.at(row, col - 1)+ img.at(row + 1, col + 1) - img.at(row + 1, col - 1), 2) + pow(img.at(row + 1, col - 1) - img.at(row - 1, col - 1) + img.at(row + 1, col) - img.at(row - 1, col) + img.at(row + 1, col + 1) - img.at(row - 1, col + 1), 2)));
}
}
imshow("Prewitt圖像(街區(qū)距離)", Prewitt_City);
imshow("Prewitt圖像(歐幾里得距離)", Prewitt_Ojld);
int pixel_num01[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Prewitt_Ojld.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int times = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< times<< "的數(shù)目為: "<< pixel_num01[times]<< endl; // 遍歷輸出
times++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Prewitt_Ojld.at(row, col)< 70) {
Prewitt_Ojld.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Prewitt_Ojld.at(row, col) = 255;
}
}
}
imshow("歐幾里得閾值分割", Prewitt_Ojld);
int pixel_num02[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Prewitt_City.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int time = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< time<< "的數(shù)目為: "<< pixel_num02[time]<< endl; // 遍歷輸出
time++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Prewitt_City.at(row, col)< 70) {
Prewitt_City.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Prewitt_City.at(row, col) = 255;
}
}
}
imshow("街區(qū)距離閾值分割", Prewitt_City);
waitKey(0);
destroyAllWindows();
}
void Sobel(Mat& img) { // 基于Prewitt算子的閾值分割
Mat Sobel_City = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算城市距離的空白圖像
Mat Sobel_Ojld = Mat::zeros(Size(img.cols, img.rows), img.type()); //用于計(jì)算歐幾里得距離的空白圖像
for (int row = 1; row< img.rows - 1; row++) {
for (int col = 1; col< img.cols - 1; col++) { // 由于像素之間的加減可能會小于零,因此記得加上絕對值函數(shù)fabs()
Sobel_City.at(row, col) = saturate_cast(fabs(img.at(row - 1, col + 1) - img.at(row - 1, col - 1) + 2*img.at(row, col + 1) - 2*img.at(row, col - 1) + img.at(row + 1, col + 1) - img.at(row + 1, col - 1)) + fabs(img.at(row + 1, col - 1) - img.at(row - 1, col - 1) + 2*img.at(row + 1, col) - 2*img.at(row - 1, col) + img.at(row + 1, col + 1) - img.at(row - 1, col + 1)));
}
}
for (int row = 1; row< img.rows - 1; row++) {
for (int col = 1; col< img.cols - 1; col++) {
Sobel_Ojld.at(row, col) = saturate_cast(sqrt(pow(img.at(row - 1, col + 1) - img.at(row - 1, col - 1) + 2*img.at(row, col + 1) - 2*img.at(row, col - 1) + img.at(row + 1, col + 1) - img.at(row + 1, col - 1), 2) + pow(img.at(row + 1, col - 1) - img.at(row - 1, col - 1) + 2*img.at(row + 1, col) - 2*img.at(row - 1, col) + img.at(row + 1, col + 1) - img.at(row - 1, col + 1), 2)));
}
}
imshow("Sobel圖像(街區(qū)距離)", Sobel_City);
imshow("Sobel圖像(歐幾里得距離)", Sobel_Ojld);
int pixel_num01[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Sobel_Ojld.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int times = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< times<< "的數(shù)目為: "<< pixel_num01[times]<< endl; // 遍歷輸出
times++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Sobel_Ojld.at(row, col)< 70) {
Sobel_Ojld.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Sobel_Ojld.at(row, col) = 255;
}
}
}
imshow("歐幾里得閾值分割", Sobel_Ojld);
int pixel_num02[256] = { 0 }; //數(shù)組記得初始化為0,即未統(tǒng)計(jì)數(shù)量之前各個(gè)像素的個(gè)數(shù)都是0
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) {
pixel_num01[Sobel_City.at(row, col)] += 1; //遍歷到的像素值作為索引,次數(shù)+1
}
}
int time = 0; //定義遍歷數(shù)組的變量,從0開始,依次輸出0到255每個(gè)像素值的數(shù)目
while (times<= 255) {
cout<< "像素值"<< time<< "的數(shù)目為: "<< pixel_num02[time]<< endl; // 遍歷輸出
time++; // 不要忘了自增
}
//得到10作為分割閾值
for (int row = 0; row< img.rows; row++) {
for (int col = 0; col< img.cols; col++) { //遍歷所有像素點(diǎn)進(jìn)行判斷
if (Sobel_City.at(row, col)< 70) {
Sobel_City.at(row, col) = 0; // 小于閾值賦值為0,否則賦值255
}
else {
Sobel_City.at(row, col) = 255;
}
}
}
imshow("街區(qū)距離閾值分割", Sobel_City);
waitKey(0);
destroyAllWindows();
}
補(bǔ)充:
由于處理空白圖像的像素值時(shí)沒有考慮到最外面的一層,因此會出現(xiàn)有像素保持為初始值0的情況。一種改進(jìn)的方法是給這些像素賦值為離它最近的像素值,這樣的話一定程度上解決了邊界全黑的問題。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)頁標(biāo)題:C++手敲Roberts-創(chuàng)新互聯(lián)
本文鏈接:http://biofuelwatch.net/article/dpgpeh.html