在实际的操作当中,opencv和halcon 都是有分割图像的函数
opencv分割图像
vector<Mat> channels;
split(image1, channels);//分割image1的通道
split(imageROI2, channels);
Mat channels1 = channels[0];//获取通道1
Mat channels2 = channels[1];//获取通道2
Mat channels3 = channels[2];//获取通道3
halcon分割图像
decompose3 (Image5, ImageR, ImageG, ImageB)
C++实现:
void RGB_Split(unsigned char *Src, unsigned char *B, unsigned char *G, unsigned char *R, int Width, int Height, int Stride)
{
//直接遍历
int channle = Stride / Width;
if (3 == channle)
{
for (int i = 0; i < Width*Height*channle; i+= channle)
{
int x = i / 3;
B[x] = Src[i];
G[x] = Src[i+1];
R[x] = Src[i + 2];
}
}
}
sse加速:
void RGB_SplitSSE(unsigned char *Src, unsigned char *B, unsigned char *G, unsigned char *R, int Width, int Height, int Stride)
{
//直接遍历
int channle = Stride / Width;
if (3 == channle)
{
int blocksize = 48;
int block = Width*Height*channle / blocksize;
for (int i = 0; i < blocksize*block; i += 48)
{
//先读进来16像素,16*3
__m128i one = _mm_loadu_si128((__m128i*)(Src + i));
__m128i two = _mm_loadu_si128((__m128i*)(Src + i+16));
__m128i three = _mm_loadu_si128((__m128i*)(Src + i+32));
//用_mm_shuffle_epi8来获取BGR数据
__m128i maskone_b = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0);
__m128i maskone_g = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1);
__m128i maskone_r = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, 11, 8, 5, 2);
__m128i dataone_b = _mm_shuffle_epi8(one, maskone_b);
__m128i dataone_g = _mm_shuffle_epi8(one, maskone_g);
__m128i dataone_r = _mm_shuffle_epi8(one, maskone_r);
__m128i masktwo_b = _mm_set_epi8(-1, -1, -1, -1, -1, 14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1);
__m128i masktwo_g = _mm_set_epi8(-1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1);
__m128i masktwo_r = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1, -1, -1, -1, -1, -1);
__m128i datatwo_b = _mm_shuffle_epi8(two, masktwo_b);
__m128i datatwo_g = _mm_shuffle_epi8(two, masktwo_g);
__m128i datatwo_r = _mm_shuffle_epi8(two, masktwo_r);
__m128i maskthree_b = _mm_set_epi8(13, 10, 7, 4, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
__m128i maskthree_g = _mm_set_epi8(14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
__m128i maskthree_r = _mm_set_epi8(15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1);
__m128i datathree_b = _mm_shuffle_epi8(three, maskthree_b);
__m128i datathree_g = _mm_shuffle_epi8(three, maskthree_g);
__m128i datathree_r = _mm_shuffle_epi8(three, maskthree_r);
__m128i dataB = _mm_or_si128(dataone_b, _mm_or_si128(datatwo_b, datathree_b));
__m128i dataG = _mm_or_si128(dataone_g, _mm_or_si128(datatwo_g, datathree_g));
__m128i dataR = _mm_or_si128(dataone_r, _mm_or_si128(datatwo_r, datathree_r));
int x = i / 3;
_mm_storeu_si128((__m128i *)(B + x), dataB);
_mm_storeu_si128((__m128i *)(G + x), dataG);
_mm_storeu_si128((__m128i *)(R + x), dataR);
}
for (int i = block*blocksize; i < Width*Height*channle; i += 3)
{
int x = i / 3;
B[x] = Src[i];
G[x] = Src[i + 1];
R[x] = Src[i + 2];
}
}
}
在使用sse加速的时候,注意_mm_set_epi8和_mm_setr_epi8这两个指令的区别,前者是从高位到低位,后者是从低位到高位,一开始我搞错了,导致出来的结果不对。