Thứ tự của mô hình màu RBG trong opencv là gì

Cách truy cập 1d trên
X là hàng. Y là cột phải k anh nhỉ

Nếu là không GUI thì có thể dùng hàm cv::imshow(titlename, mat); để show một bức ảnh lên.
Nó sẽ hiển thị bức ảnh lên một cửa sổ có title = titlename.

cv::Mat* mat = new cv::Mat();
cv::imshow("Show Mat",mat[0]);

Bức ảnh có thể coi là một ma trận pixel có gốc ở phía trên bên trái.
Từ gốc này đi theo hướng ngang là hướng X.
Và đi xuống dưới là hướng Y.
X và Y là tọa độ của pixel.

1 Like

Thì e dùng imshow đó nên mới phải đẩy dữ liệu ảnh vào Mat. E sẽ thử cách trên.em muốn tìm cách thao tác nhanh nhất ấy ạ

em thử mà dữ liệu nó ra không đúng anh ơi

int offset;
for (int i = 0; i < image.rows; i++){
	for(int j = 0; j < image.cols; j++){
		offset = j*image.step + i*image.channels();
		cout << (unsigned int)image.data[offset + 0] << " ";
		cout << (unsigned int)image.data[offset + 1] << " ";
		cout << (unsigned int)image.data[offset + 2] << " ";
	}
	cout << endl;
}

ảnh cout << Mat của opencv

ảnh duyệt bàng cách trên và in ra theo thứ tự bgr

cách 2d cũng in ra sai giá trị ạ

unsigned char **ptr = new unsigned char*[image.rows];
	for (int i = 0; i < image.rows; i++) ptr[i] = image.data + i*image.step;
	int offset; 
	for (int i = 0; i < image.rows; i++){
            offset = i*image.channels();
		for (int j = 0; j < image.cols; j++){
			cout << (unsigned int)ptr[j][offset + 0]  << " ";
			cout << (unsigned int)ptr[j][offset + 1] << " ";
			cout << (unsigned int)ptr[j][offset + 2] << " ";
		}
		cout << endl;
	}

Mat đầu là cout << mat của opecv
Mat 2 là duyệt in ra theo cách 2d trên

Ở đoạn 1D:

int offset;
for (int i = 0; i < image.rows; i++){
	for(int j = 0; j < image.cols; j++){
		offset = j*image.step + i*image.channels(); // j là đại diện cho x sao nhân với step ?
                // offset = i*image.step + j*image.channels(); // phải thế này chứ ?
                ///.....
	}
	cout << endl;
}

Sao lại đi nhân x với step ?
step là số byte trên 1 line. Phải nhân y với step để tìm ra vị trí byte đầu tiên của 1 line. Sau đó sẽ cộng thêm x nhân với số byte của 1 pixel để tìm ra byte đầu tiên của pixel chứ ?

Ở 2D:

unsigned char **ptr = new unsigned char*[image.rows];
	for (int i = 0; i < image.rows; i++) ptr[i] = image.data + i*image.step;
	int offset; 
	for (int i = 0; i < image.rows; i++){
            offset = i*image.channels(); // sao lại gán offset ở đây
		for (int j = 0; j < image.cols; j++){
                       // offset = j*image.channels(); // offset phải gán thế này chứ ?
			cout << (unsigned int)ptr[j][offset + 0]  << " ";
			cout << (unsigned int)ptr[j][offset + 1] << " ";
			cout << (unsigned int)ptr[j][offset + 2] << " ";
		}
		cout << endl;
	}

Ở 2 D sẽ khai báo y (hoặc rows) con trỏ để trỏ đến từng byte đầu tiên của các line. Mỗi line có step byte nên mới có công thức này:

for (int i = 0; i < image.rows; i++) ptr[i] = image.data + i*image.step;

Để truy cập đến byte đầu của 1 pixel ta nhân x với channels rồi truy cập tới con trỏ của mỗi line.
Vậy mới có:

int offset = x*image.channels;
pixelR = ptr[y][offset+2];
pixelG =ptr[y][offset+1];
pixelB = ptr[y][offset+0];

Như bạn để ý code 2D thì phần gán offset đang để ở ngoài vòng for duyệt x ??
offset là vị trí của byte đầu tiên của pixel trên 1 line. Do vậy phải gán trong vòng for với x mới đúng.


Ngoài lề chút là các biến I,j,k trong for bạn nên đặt tên rõ là x,y thì trong sang và dễ tìm lỗi nhé.

1 Like

:smiley: Thank anh, e hay dùng i duyệt cho dòng, j cho cột, nên sáng x, y bị lộn

Vậy nó đã chạy OK chưa ? (20 char)

1 Like

Em đang viết báo cáo hàng tuần để nạp, nên chưa thử ạ, nhưng a nhắc lại chỗ x,y hàng cột thì e nhớ ra em sai chỗ i, j rồi :smile: Tối về em thử, Tks anh

Em đã thử ok rồi ạ. Vì em để i,j,k nên lộn với x,y :smile: tks anh

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?