OpenCV--图像数字化
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;
#include<iostream>
using namespace std;
void showMat_Int(Mat e) {
if (e.dims == 1) {
for (int i = 0; i < e.total(); i++) {
cout << e.at<int>(i) << ",";
}
cout << endl;
return;
}
if (e.dims == 2) {
for (int i = 0; i < e.rows; i++) {
const int* ptr = e.ptr<int>(i);
for (int j = 0; j < e.cols; j++) {
cout << ptr[j] << ",";
}
cout << endl;
}
}
}
void showMat_Float(Mat e) {
if (e.dims == 1) {
for (int i = 0; i < e.total(); i++) {
cout << e.at<float>(i) << ",";
}
cout << endl;
return;
}
if (e.dims == 2) {
for (int i = 0; i < e.rows; i++) {
const float* ptr = e.ptr<float>(i);
for (int j = 0; j < e.cols; j++) {
cout << ptr[j] << ",";
}
cout << endl;
}
}
}
void showMat_Vec3i(Mat e) {
for (int i = 0; i < e.rows; i++) {
Vec3i* ptr = e.ptr<Vec3i>(i);
for (int j = 0; j < e.cols; j++) {
cout << ptr[j] << ",";
}
cout << endl;
}
}
int show_img_G()//G为灰度图片
{ //导图
Mat img = imread("D://Study//OpenCV算法精解代码//OpenCV测试图片//第3章//img.jpg", IMREAD_GRAYSCALE);
//改动窗口名
string winname = "原图";
namedWindow(winname, WINDOW_AUTOSIZE);
//显示图片
imshow(winname, img);
waitKey();
return 0;
}
int show_img_C() {
Mat img = imread("D://Study//OpenCV算法精解代码//OpenCV测试图片//第3章//img3.jpg", IMREAD_COLOR);
imshow("BGR",img);
vector<Mat> planes;
split(img, planes);
imshow("B", planes[0]);
imshow("G", planes[1]);
imshow("R", planes[2]);
waitKey();
return 0;
}
int main(int argc,char*argv[]) {
Mat m = Mat::ones(2, 3, CV_32FC(1));
cout << m.cols;//得到m的行数
cout << m.rows;//得到m的列数
cout << endl;
for (int i = 0; i < m.rows; i++) {
for (int j = 0; j < m.cols; j++) {
cout << m.at<float>(i,j)<<" ";//矩阵的遍历,得到i,j位置的矩阵值用at函数
//还可以利用point函数将i,j变成坐标的形式
//cout<<m.at<float>(Point(i,j));(不知道意义在哪doge)
}
cout << endl;
}
cout << endl;
cout << "m的面积为" << m.total() << endl;
cout << "m的通道数为" << m.channels() << endl;//上面两个为成员方法
cout << "m的维数为" << m.dims << endl;//维数为成员变量
cout << "================================"<<endl;
//mat类的数值是以连续的一行存在内存中的,在此可以利用ptr的到每一行的首元素的地址,以此遍历整个mat
for (int r = 0; r < m.rows; r++) {
const float * ptr = m.ptr<float>(r);//在用ptr函数时,数据类型必须和矩阵mat的类型一致,否则将无法打印
for (int j = 0; j < m.cols; j++) {
cout << ptr[j]<<",";
}
cout << endl;
}
//m.isContinuous()判断m是不是在内存中连续存储
cout << endl << m.isContinuous() << endl;
if (m.isContinuous()) {
const float* ptr1 = m.ptr<float>(0);
for (int i = 0; i < m.total(); i++) {
cout << ptr1[i]<<",";
}
}
cout << endl << "=====================" << endl;
// 向量vec,直接理解为列向量;
Vec<int, 4> vi(1, 2, 3, 4);
//vec同样可以具有rows、cols,访问向量中的值可以利用[]或者()访问
cout << vi.rows << endl;
cout << vi.cols << endl;
cout << vi[0];
//Vec被Opencv重命名例如
/*
* typedef Vec<uchar,3>vec3b
* typedef Vec<int,2>vec2i;
*/
cout << "===============多通道======" << endl;
//前面的方法都是基于单通道,下面介绍多通道
//1.建立多通道mat,形式:Mat(int rows,int cols,CV_32FC(n)),n就是通道数
Mat mm = (Mat_<Vec3i>(2, 2) << Vec3i(1, 2, 3), Vec3i(4, 5, 6),
Vec3i(7, 8, 9), Vec3i(10, 11, 12));
//at函数,在此处将多通道的Mat看为一个特殊的二维数组,每个元素都是一个列向量
cout << "以at方式遍历" << endl;
for (int i = 0; i < mm.rows; i++) {
for (int j = 0; j < mm.cols; j++) {
cout << mm.at<Vec3i>(i, j) << ",";
}
cout << endl;
}
//ptr函数,同样的,多通道在内存中也是以一行存储;
cout << "以ptr方式遍历" << endl;
for (int i = 0; i < mm.rows; i++) {
Vec3i* ptr = mm.ptr<Vec3i>(i);
for (int j = 0; j < mm.cols; j++) {
cout << ptr[j] << ",";
}
cout << endl;
}
//isContinuous()和ptr,同样的该函数是判断此矩阵是否在内存中连续,如果返回true,可以利用一层循环遍历
if (mm.isContinuous()) {
Vec3i* ptr = mm.ptr<Vec3i>(0);
for (int i = 0; i < mm.total(); i++) {
cout << ptr[i] << ",";
}
}
cout << endl;
cout << "==========================" << endl;
//分离通道以及合并通道
//以mm为例,该Mat可以利用split函数分离多通道放在vector容器中;
vector<Mat> planes;
split(mm, planes);
for (int i = 0; i < planes.size(); i++) {
cout << planes[i] << ",";
}
cout << endl << "=======================" << endl;
//合并通道,利用merge函数可以将多个单通道函数合并为多通道
Mat plane0 = (Mat_<int>(2, 2) << 1, 2, 3, 4);
Mat plane1 = (Mat_<int>(2, 2) << 5, 6, 7, 8);
Mat plane2 = (Mat_<int>(2, 2) << 9, 10, 11, 12);
Mat planes1[] = { plane0,plane1,plane2 };
Mat mat;
merge(planes1, 3, mat);
showMat_Vec3i(mat);
cout << "=====================";
//得到矩阵的某一部分值
cout << "得到矩阵的某一部分值:" << endl;
Mat matrix = (Mat_<int>(5, 5) << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25);
//的到matrix的第二行和第三行
Mat r_range = matrix.rowRange(Range(2, 4));
//得到matrix的第二列和第三列
Mat c_range = matrix.colRange(Range(2, 4));
showMat_Int(r_range);
cout << "=====================\n";
showMat_Int(c_range);
cout << "=====================\n";
//该方法是引用了matrix的地址,若在c_range中修改数值,会导致matrix中的数值也会修改
//若不想修改数值,我们要使用clone或者copyto方法,例如:
Mat c_range_clone = matrix.colRange(Range(2, 4)).clone();
showMat_Int(c_range_clone);
cout << "=====================\n";
//如果我们想得到该矩阵中的某一块子矩阵,我们可以使用Rect类,形式如下
//Rect(int x,int y,int width,int highe)或者Rect(int x,int y,Size size)或者Rect(point 1,point 2)
Mat rect_mat = matrix(Rect(Point(1, 1), Point(3, 3)));
showMat_Int(rect_mat);
cout << "=====================\n";
//矩阵加法,减法,点乘,点除,乘方,其他
Mat src1 = (Mat_<int>(2, 3) << 1, 2, 3, 4, 5, 6);
Mat src2 = (Mat_<int>(2, 3) << 7, 8, 9, 10, 11, 12);
//"+"被opencv重载,可以直接使用在相同类型的矩阵中,数值会被数据类型限制,add方法则会自动转换数据类型,接下来只会介绍以方法类型的操作
//值得注意的是,这些方法具备重载形式,不仅可以进行矩阵间运算,还可以进行矩阵和数值的运算
Mat dst;
add(src1, src2, dst, Mat(), CV_32S);
showMat_Int(dst);
cout << "=======================\n";
//减法类似于加法
Mat det1;
subtract(src1, src2, det1, Mat(), CV_32S);
showMat_Int(det1);
cout << "=======================\n";
//点乘和点除,系数scale为点除结果乘上scale
Mat det2, det3;
multiply(src1, src2, det2, 1, CV_32S);
divide(src1, src2, det3, 1, CV_32S);
//乘方,参考数学中的左行右列,直接使用“*”运算符即可,注意的是,双通道进行计算是将两个Mat当成复数矩阵
//exp和log函数分别计算指数和对数,pow和sqrt分别计算幂指数和开平方
cout << "==========================\n";
//灰度图片数字化
show_img_G();
//彩色图片数字化
show_img_C();
return 0;
}
本文介绍了OpenCV中的图像数字化处理,包括灰度和彩色图片的读取、Mat类元素的遍历、多通道处理、矩阵运算和图像展示。通过实例展示了如何使用Mat类的成员方法和指针进行内存访问以及基本的图像操作。
5230

被折叠的 条评论
为什么被折叠?



