rgb图像三通道分割 opencv halcon实现以及c++底层实现和sse加速

在实际的操作当中,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这两个指令的区别,前者是从高位到低位,后者是从低位到高位,一开始我搞错了,导致出来的结果不对。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值