利用Mat对象的像素数组指针来修改图片,是老司机玩的,新手的话可以采用一些安全访问的办法。
见下面的代码。
演示代码:
C++
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//imread 可以指定加载为灰度或者RGB图像
Mat src=imread("e:/5.png",IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "载入图片失败..." << endl;
return -1;
}
imshow("win1",src);
//Imwrite 保存图像文件,类型由扩展名决定
imwrite("e:/5gray.bmp",src);
printf("src的通道数:%d\n", src.channels());
//单通道修改像素,反相效果
//效果见图1
int row = src.rows;
int col = src.cols;
int channels = src.channels();
for (int i = 0; i < row; i++) {
for (int k = 0; k < col; k++) {
if (channels == 1) {
int g=src.at<uchar>(i, k);
src.at<uchar>(i, k) = 255 - g;
}
}
}
imshow("win2", src);
//3通道图像反相显示,效果见图2
Mat src2 = imread("e:/5.png");
imshow("win3", src2);
row = src2.rows;
col = src2.cols;
channels = src2.channels();
Mat src3 = src2.clone();
for (int i = 0; i < row; i++) {
for (int k = 0; k < col; k++) {
if (channels == 3) {
int b = src3.at<Vec3b>(i, k)[0];
int g = src3.at<Vec3b>(i, k)[1];
int r = src3.at<Vec3b>(i, k)[2];
src3.at<Vec3b>(i, k)[0] = 255 - b;
src3.at<Vec3b>(i, k)[1] = 255 - g;
src3.at<Vec3b>(i, k)[2] = 255 - r;
}
}
}
imshow("win4", src3);
//bitwise_not是对二进制数据进行“非”操作,
//即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“非”操作
//效果和上面的代码是一样的。
Mat src4;
src4.create(src2.size(), src2.type());
bitwise_not(src2, src4);
imshow("win5", src4);
//利用3通道,用min,max函数计算出新的单通道灰度图
//效果见图3
src3 = src2.clone();
Mat gray2,gray3;
cvtColor(src3, gray2, COLOR_BGR2GRAY);
gray3 = gray2.clone();
printf("gray2通道数:%d\n", gray2.channels());
for (int i = 0; i < row; i++) {
for (int k = 0; k < col; k++) {
if (channels == 3) {
int b = src3.at<Vec3b>(i, k)[0];
int g = src3.at<Vec3b>(i, k)[1];
int r = src3.at<Vec3b>(i, k)[2];
gray2.at<uchar>(i, k) = max(r, max(g, b));
gray3.at<uchar>(i, k) = min(r, min(g, b));
}
}
}
imshow("win6", gray2);
imshow("win7", gray3);
waitKey(0);
return 0;
}
(图1)
(图2)
(图3)
代码说明:
C#
imread 可以指定加载为灰度或者RGB图像
Imwrite 保存图像文件,类型由扩展名决定
C++
读一个GRAY像素点的像素值(CV_8UC1)
Scalar intensity = img.at<uchar>(y, x);
或者 Scalar intensity = img.at<uchar>(Point(x, y));
读一个RGB像素点的像素值
Vec3f intensity = img.at<Vec3f>(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];
修改像素值 :
C++
灰度图像 img.at<uchar>(y, x) = 128;
RGB三通道图像
img.at<Vec3b>(y,x)[0]=128; // blue
img.at<Vec3b>(y,x)[1]=128; // green
img.at<Vec3b>(y,x)[2]=128; // red
空白图像赋值 img = Scalar(0);
ROI选择 Rect r(10, 10, 100, 100);
Mat smallImg = img(r);
Vec3b与Vec3F:
C++
Vec3b对应三通道的顺序是blue、green、red的uchar类型数据。
Vec3f对应三通道的float类型数据
把CV_8UC1转换到CV32F1实现如下: src.convertTo(dst, CV_32F);
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文章代码及资料部分或全部来自贾志刚老师的视频,勇哥只是在个人理解的基础上做学习笔记,转载请附上博文链接!
本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:


