- The matrix of the 3 channels of picture pixels is arranged as follows:
- [[r11,g11,b11, r12, g12, b12, r13, g13, b13,.........], [r_ij, g_ij, b_ig,],[............]]
- That is, the first line has: [r11, g11, b11, r12, g12, b12, r13,g13,b13]
- The RGB values of the ij-th pixel are continuous together, instead of: [r11,r12,r13, g11,g12, g13, b11,b12,b13]
- Mask
- It comes from silicon wafer carving, which means to select an area on the silicon wafer and cover it with a board, and then everything except the place covered by the board is engraved.
-
Image mask
-
It is to use an image\graphics\object\matrix to cover the image to be processed to affect the processed area.
-
- Mask usage:
- Region of interest: it is the image\graphics\object\matrix mentioned above, multiply the pre-made region of interest mask and the image to be processed to obtain the image of interest, the region of interest
- First get the value of the image pixel: by image pixel pointer
- Mat.ptr<uchar>(int i =0) gets the pointer of the pixel matrix, the index i indicates the number of rows, starting from 0
- const uchar* current = myImage.ptr<uchar>(row);
- The row is unchanged and the column is changed to obtain the pixel value of the pixel p(row,col) = current[col];
- Then make sure that the input image is of uchar type, use the CV_Assert function to distinguish, and the parameter is FALSE to return ERROR
- CV_Assert(MyImage.depth() == CV_8U);
- Finally, some pixel values are processed
- I(i,j) = 5*I(i,j) - [ I(i-1,j) + I(i+1,j) + I(i, j-1)+ I(i, j+1)]
#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <cmath>
using namespace std;
using namespace cv;
int main(int argc, char ** argv)
{
Mat myImage = imread("图片地址");
CV_Assert(myImage.depth() == CV_8U);
namedWindow("mask_demo", WINDOW_AUTOSIZE);
imshow("mask_demo", myImage);
Mat resultImage;
myImage.copyTo(resultImage);
int nchannels = myImage.channels();
int height = myImage.rows;
int cols = myImage.cols;
int width = myImage.cols*nchannels;
for (int row = 1; row < height - 1; row++)
{
const uchar * previous = myImage.ptr<uchar>(row - 1);
const uchar*current = myImage.ptr<uchar>(row);
const uchar* next = myImage.ptr<uchar>(row + 1);
uchar * output = resultImage.ptr<uchar>(row);
for (int col = nchannels; col < nchannels*(myImage.cols - 1); col++)
{
*output = saturate_cast<uchar>(5 * current[col] - previous[col] - next[col] - current[col - nchannels] - current[col + nchannels]);
output++;
}
}
namedWindow("mask_result", WINDOW_AUTOSIZE);
imshow("mask_result", resultImage);
waitKey(0);
return 0;
}
- As shown in the figure, the row does not change and the column changes. It is easy to determine row, but col is more difficult.
- The difficulty is that I didn't figure out the specific arrangement of the pixel matrix before, and I made the following table after querying (assuming to start from 11)
- The consecutive gray and white are the values of the three channels below the pixel
- current[col-nchannels] is the subscript of g22 -3 is the subscript of g21
- The value of rgb corresponds to addition and subtraction. You cannot use the value of the r channel to calculate with the value of the g channel.
- Using API, that is, function to perform mask calculation is much simpler than the above
- Define a mask
- Mat kernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1, 0,-1,0);
- filter2D(src, dst, src.depth(), kernel);
- src and dst are Mat objects
- src.depth is the bitmap depth, 32, 24, 8, etc.
- filter is the classifier
- Define a mask
int main(int argc, char ** argv)
{
Mat src,dst;
src = imread("地址");
if(!src.data)
{
cout<<"no imgae";
return -1;
}
namedWindow("src_image", WINDOW_AUTOSIZE);
imshow("src_image", src);
Mat Kernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
filter2D(src, dst,src.depth(),Kernel);
namedWindow("kernel_image", WINDOW_AUTOSIZE);
imshow("kernel_image", dst);
waitKey(0);
return 0;
}