- 本节内容:图像像素操作:遍历与访问
C++
在C++中访问OpenCV Mat对象每个像素点的像素值有两种方式:
- 通过数组,逐个访问每个像素点的每个通道;
- 通过指针访问数组的像素点的地址,然后从地址中取像素值 ---- 效率更高;
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int artc, char** argv) {
Mat src = imread("D:/vcprojects/images/test.png");
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
namedWindow("input", CV_WINDOW_AUTOSIZE);
imshow("input", src);
// 直接读取图像像素:遍历访问,速度慢
int height = src.rows; //读取图像高、宽、通道数
int width = src.cols;
int ch = src.channels(); //通道为3则为彩色图像,每个像素点有三个值;通道为1则为黑白图像,每个像素点有一个值。另外还有四通道图,为透明通道,若alpha=0则完全透明,alpha=255则完全不透明。
for (int c = 0; c < ch; c++) {
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (ch == 3) {
Vec3b bgr = src.at<Vec3b>(row, col);//Vec3b是一个数据结构;Mat.at<Vec3b>(row, col)表示获取Mat在(row,col)位置的三个字节类型的值,存入Vec3b数据结构中
bgr[0] = 255 - bgr[0];//实现图像色彩取反。像素值范围为[0,255]
bgr[1] = 255 - bgr[1];
bgr[2] = 255 - bgr[2];
src.at<Vec3b>(row, col) = bgr; //对原像素点赋取反后的值
} else if(ch == 1) {
int gray = src.at<uchar>(row, col);
src.at<uchar>(row, col) = 255 - gray;
}
}
}
}
imshow("output", src);
// 指针读取。代码展示了如何通过指针将原像素拷贝到另外一个Mat对象中。
Mat result = Mat::zeros(src.size(), src.type()); //创建空白图像
int blue = 0, green = 0, red = 0;
int gray;
for (int c = 0; c < ch; c++) {
for (int row = 0; row < height; row++) {
uchar* curr_row = src.ptr<uchar>(row);//Mat.ptr<uchar>(row)的作用是获取这一行所有像素点的像素块的首地址
uchar* result_row = result.ptr<uchar>(row);//得到要输出的那一行的地址
for (int col = 0; col < width; col++) { //对每一列遍历
if (ch == 3) { //对于三通道图像,列数*3是像素块的遍历次数
blue = *curr_row++;
green = *curr_row++;
red = *curr_row++;
*result_row++ = blue;
*result_row++ = green;
*result_row++ = red;
}
else if (ch == 1) {
gray = *curr_row++;
*result_row++ = gray;
}
}
}
}
imshow("result", result);
waitKey(0);
return 0;
}
Python
import cv2 as cv
src = cv.imread("D:/vcprojects/images/test.png")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
h, w, ch = src.shape #获取图像高、宽、通道数。如果图像为灰度图,则img.shape只会返回h和w
print("h , w, ch", h, w, ch)
for row in range(h): #横向和纵向都是从0开始索引
for col in range(w):
b, g, r = src[row, col] #直接读取到三个通道的值
b = 255 - b
g = 255 - g
r = 255 - r
src[row, col] = [b, g, r] #将原图像上的对应像素取反
cv.imshow("output", src)
cv.waitKey(0)
cv.destroyAllWindows()
网友评论