简介
首先其实彩虹图就是灰度图按照对应关系
灰度0-255 转换为RGB:红、橙、黄、绿、青、蓝
由于在xfopencv中的xf::Mat这个类型没有at方法,则我们需要编写一个读写Mat结构的方法。具体分析:
- 一个读灰度图像素值的方法
- 一个写RGB图像素值的方法
- 一个转换算法
具体分析
1.一个读灰度图像素值的方法
首先我们知道Mat存灰度就是一个数据单元存放一个对应的0-255的值,类型是uchar
那么我们的读取要从2维转换到1维上。因为在内存中Mat的存放是一维的,按行存储。
则我们用 x,y坐标访问这个数组就应该是
data[x+y*cols];
因为每行就是cols个值,cols相当于是宽度,按照 x+y*cols 我们就能够访问到 x列 y行的数据存放的值了。
具体方法:
uchar getPixel(Mat mat,int x,int y) {
return mat.data[x + y * mat.cols];
}
2.一个写RGB图像素值的方法
RGB和灰度图有所不同,因为RGB图存储大小是灰度图的三倍。在内存中是BGR为一个块的大小。
一共是cols*rows个块。
这样我们用x y 去写入色值时,我们要分对B、G、R 哪一个块内色值写入。我们用 channle表示是对哪一个通道写值,则我们的方法可以表示为:
void setBGRPixel(Mat mat, int x, int y, uchar pixel,int channle) {
mat.data[(x + y * mat.cols )*3 + channle ] = pixel;
}
3.一个转换算法
转换算法就很简单了 一个对每个图像像素点的遍历就行了。
void gray2Rainbow(Mat src,Mat out) {
uchar tmp;
for (int x = 0; x < src.cols; x++) {
for (int y = 0; y < src.rows; y++) {
tmp = getPixel(src, x, y);
if (tmp <= 51) {
setBGRPixel(out, x, y, 255, 0);
setBGRPixel(out, x, y, tmp * 5, 1);
setBGRPixel(out, x, y, 0, 2);
}
else if (tmp <= 102) {
tmp -= 51;
setBGRPixel(out, x, y, 255 - tmp * 5, 0);
setBGRPixel(out, x, y, 255, 1);
setBGRPixel(out, x, y, 0, 2);
}
else if (tmp < 153) {
tmp -= 102;
setBGRPixel(out, x, y, 0, 0);
setBGRPixel(out, x, y, 255, 1);
setBGRPixel(out, x, y, tmp * 5, 2);
}
else if (tmp < 204) {
tmp -= 153;
setBGRPixel(out, x, y, 0, 0);
setBGRPixel(out, x, y, 255 - uchar(128.0 * tmp / 51.0 + 0.5), 1);
setBGRPixel(out, x, y, 255, 2);
}
else {
tmp -= 204;
setBGRPixel(out, x, y, 0, 0);
setBGRPixel(out, x, y, 127 - uchar(127.0 * tmp / 51.0 + 0.5), 1);
setBGRPixel(out, x, y, 255, 2);
}
}
}
}
最后的效果
在xfopenCv上实现
由于,在xfopencv中 单通道图像的像素数据类型是ap_uint<8>,而RGB色值直接就是 ap_unit<24>来存储的,因此我们需要稍微修改一下我们的代码:
void gray2rainbow(GrayMat &mat1,ColorMat &mat2){
ap_uint<8> pix_gray;
ap_uint<24> pix_BGR;
for (int x = 0; x <mat1.cols; x++) {
for (int y = 0; y < mat1.rows; y++) {
pix_gray = mat1.data[x+y*WIDTH];
if(pix_gray < 51){
mat2.data[x+y*WIDTH]=0x0000ff + 0x000100*pix_gray;
}
else if (pix_gray <= 102 && pix_gray > 51) {
pix_gray=pix_gray-51;
mat2.data[x+y*WIDTH]=0x00ffff-pix_gray*5;
} else if(pix_gray < 153 && pix_gray>102){
pix_gray=pix_gray-102;
mat2.data[x+y*WIDTH]=0x00ff00+0x050000*pix_gray;
}else if(pix_gray < 204 && pix_gray > 153 ){
pix_gray=pix_gray-153;
mat2.data[x+y*WIDTH]=0xffff00-0x000100*(ap_uint<24>(128.0*pix_gray/51.0+0.5));
}else {
pix_gray=pix_gray-204;
mat2.data[x+y*WIDTH]=0xff8000-0x000100*(ap_uint<24>(127.0*pix_gray/51.0+0.5));
}
}
}
}
按照上诉算法即可得到下图的效果。
最后按照自定义的接口axis或者axiLite约束一下接口就可以综合生成IP核了。这里就不赘述啦。