目录
一、逐像素的图像复制
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;
}
?有出错的地方欢迎大家纠错!
|