OpenCV(二)逐像素的图像复制、图像边缘检测(自实现和API实现)
生活随笔
收集整理的這篇文章主要介紹了
OpenCV(二)逐像素的图像复制、图像边缘检测(自实现和API实现)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
一、逐像素的圖像復制
1、代碼
2、效果
二、簡單的圖像邊緣檢測(自實現)
0、圖像處理的卷積運算
1、簡單模糊處理
?2、強化邊緣處理
1、原理
2、代碼
?3、效果
三、簡單的圖像邊緣檢測(調用API)
1、設置卷積核kernel
2、利用filter()函數進行卷積運算
?3、總代碼
一、逐像素的圖像復制
這里主要是為了強化圖像的指針應用。
//圖像的指針用法舉例
cv::Mat image = cv::Mat(400, 600, CV_8UC1); //定義了一個Mat變量image。
uchar * data00 = image.ptr<uchar>(0); //data00是指向image第1行第1個元素的指針。
uchar * data10 = image.ptr<uchar>(1); //data10是指向image第1行第1個元素的指針。
uchar * data01 = image.ptr<uchar>(0)[1]; //data01是指向image第1行第2個元素的指針。
1、代碼:
//逐像素的圖像復制
#include <iostream>
#include <opencv2/opencv.hpp> using namespace cv;
using namespace std;
int main()
{int i, j;Mat img = imread("Resource/Lena.jpg");int channels = img.channels(); //通道數int cols = img.cols * channels; //列*通道數(每行需要的RGB)int rows = img.rows; //行數Mat New = Mat::zeros(img.size(), img.type()); //創建一張黑色的圖const uchar* p = img.ptr<uchar>(0); //原圖首地址uchar* pNew = New.ptr<uchar>(0); //新圖首地址if (img.empty()) //判斷圖像存在{printf("could not load the image..");return -1;}for (i = 0; i < rows; i++){p = img.ptr<uchar>(i); //指向i行首元素pNew = New.ptr<uchar>(i); //指向j行首元素for (j = 0; j <= cols; j++){pNew[j] = p[j]; //pNew的i行j元素RGB賦值p的i行j元素RGB}}namedWindow("原始圖像", WINDOW_AUTOSIZE);imshow("原始圖像", img);namedWindow("修改后圖像", WINDOW_AUTOSIZE);imshow("修改后圖像", New);waitKey(0);return 0;
}
2、效果
二、簡單的圖像邊緣檢測(自實現)
0、圖像處理的卷積運算
1、簡單模糊處理
比如說,如下圖像處理矩陣將使得圖像變得更平滑,顯得更模糊,因為它聯合周邊像素進行了平均處理:
?2、強化邊緣處理
而如下圖像處理矩陣將使得像素值變化明顯的地方更為明顯,強化邊緣,而變化平緩的地方沒有影響,達到提取邊緣的目的:
?
1、原理
在邊緣處,留心觀察發現會有RGB的突變,只需要把這個RGB突變部分給銳化,顯示在對應位置即可。(其他部分淡化)
?
?
2、代碼
//平滑處理
#include <iostream>
#include <opencv2/opencv.hpp> using namespace cv;
using namespace std;
int main()
{int i, j;Mat img = imread("Resource/Lena.jpg");if (img.empty()){printf("could not load the image..");return -1;}int cols = img.cols * img.channels(); //列*通道數int rows = img.rows; //行數int channels = img.channels(); //通道數Mat New = Mat::zeros(img.size(), img.type()); //創建一張黑色的圖const uchar* p; //原圖當前行首地址(暫時無指向)const uchar* prior; //原圖上一行首地址(暫時無指向)const uchar* next; //原圖下一行首地址(暫時無指向)uchar* pNew; //新圖當前行首地址(暫時無指向)//按行處理(每行首和尾不做處理)for (i = 1; i < rows - 1; i++){p = img.ptr<uchar>(i); //原圖當前行首地址prior = img.ptr<uchar>(i - 1); //原圖上一行首地址next = img.ptr<uchar>(i + 1); //原圖下一行首地址pNew = New.ptr<uchar>(i); //新圖當前行首地址//按列處理(每列首和尾不做處理)for (j = 0 + channels; j <= cols - channels; j++){pNew[j] = saturate_cast <uchar>(4 * p[j] - prior[j] - next[j] - p[j - channels] - p[j + channels]);// 限制RGB范圍(0~255) //p[j]:當前行當前列元素 //prior[j]:上一行當前列元素 //next[j]:下一行當前列元素// p[j - channels]:上一列像素(不是RGB) //p[j + channels]:下一列像素(不是RGB)}}namedWindow("修改前圖像", WINDOW_AUTOSIZE);imshow("修改前圖像", img);namedWindow("修改后圖像", WINDOW_AUTOSIZE);imshow("修改后圖像", New);waitKey(0);return 0;
}
?3、效果
三、簡單的圖像邊緣檢測(調用API)
1、設置卷積核kernel
//1、初始化卷積核Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
2、利用filter()函數進行卷積運算
filter2D(img, New, img.depth(), kernel);
// 原圖,目標圖,深度, 卷積核
?3、總代碼
//邊緣檢測
#include <iostream>
#include <opencv2/opencv.hpp> using namespace cv;
using namespace std;Mat img = imread("Resource/Lena.jpg"); //讀取圖像
int cols = img.cols * img.channels(); //列*通道數
int rows = img.rows; //行數
int channels = img.channels(); //通道數
Mat New = Mat::zeros(img.size(), img.type()); //創建一張黑色的圖//判斷圖像是否存在
int JudgeImage()
{if (img.empty()){printf("could not load the image..");return -1;}
}//邊緣化
void Marginalize()
{int i, j;const uchar* p; //原圖當前行首地址(暫時無指向)const uchar* prior; //原圖上一行首地址(暫時無指向)const uchar* next; //原圖下一行首地址(暫時無指向)uchar* pNew; //新圖當前行首地址(暫時無指向)//按行處理(每行首和尾不做處理)for (i = 1; i < rows - 1; i++){p = img.ptr<uchar>(i); //原圖當前行首地址prior = img.ptr<uchar>(i - 1); //原圖上一行首地址next = img.ptr<uchar>(i + 1); //原圖下一行首地址pNew = New.ptr<uchar>(i); //新圖當前行首地址//按列處理(每列首和尾不做處理)for (j = 0 + channels; j <= cols - channels; j++){pNew[j] = saturate_cast <uchar>(4 * p[j] - prior[j] - next[j] - p[j - channels] - p[j + channels]);// 限制RGB范圍(0~255) //p[j]:當前行當前列元素 prior[j]:上一行當前列元素 next[j]:下一行當前列元素// p[j - channels]:上一列像素(不是RGB) p[j + channels]:下一列像素(不是RGB)}}
}//打印卷積核
void ShowKernel(Mat kernel)
{printf("卷積核:\n");//打印卷積核for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){printf("%3d", kernel.at<char>(i, j));}printf("\n");}
}//調用API邊緣化
void API_Marginalize()
{//1、初始化卷積核Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0); //2、卷積運算filter2D(img, New, img.depth(), kernel); // 原圖,目標圖,深度, 卷積核//打印卷積核//ShowKernel(kernel);
}//顯示圖像
void Show()
{namedWindow("修改前圖像", WINDOW_AUTOSIZE);imshow("修改前圖像", img);namedWindow("修改后圖像", WINDOW_AUTOSIZE);imshow("修改后圖像", New);
}int main()
{JudgeImage(); //判斷圖像是否存在//Marginalize(); //邊緣化圖像API_Marginalize(); //調用API邊緣化Show(); //顯示圖像waitKey(0);return 0;
}
?有出錯的地方歡迎大家糾錯!
總結
以上是生活随笔為你收集整理的OpenCV(二)逐像素的图像复制、图像边缘检测(自实现和API实现)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV(一)图像读取与新建、图像显
- 下一篇: 数据结构与算法(7-3)最小生成树(普里