SSE优化系列九:小半径中值滤波的SSE极速优化(比OpenCV3.1.0快9-10倍)

图像处理小tip——中值滤波的多种实现(包括快速中值滤波算法) 文章目录中值滤波介绍opencv自带的中值滤波函数简单算法实现中值滤波快速算法实现中值滤波 中值滤波介绍 中值滤波介绍 中值滤波定义:将????(????为奇数)个数据按其值????????进行从大到小或者从小到大排列后得到一个有序序列:????0,????1, … ,????????−1,则????(????/2)称为中值。例如:有序序列10,11,12,13,14,15,16,17,18的???? = 9,有 [9/2] = 4,则中值为????4,即14。   根据以上可知,中值滤波就是以当前像素为 阅读详情

前言

在优化系列六:https://blog.youkuaiyun.com/just_sort/article/details/97280807 中提出了一个直方图算法处理框架,可以处理中值滤波,最大值滤波等,算法复杂度是和半径大小无关的。但是这里忽略了一个点在半径很小的时候,这个算法实际上是比直接暴力处理更慢的。而我们在日常图像处理过程中,小半径的中值滤波是最常用的例如3 * 3, 5 * 5 在PS中都是十分常用的。受到ImageShop的这篇博客:https://www.cnblogs.com/Imageshop/p/11087804.html 启发,所以有了这篇文章。

朴素的3*3中值模糊

这个没有什么说的,就是在半径范围里面遍历即可,这里获取中值直接使用了c语言的qsort。

int ComparisonFunction(const void *X, const void *Y) {
	unsigned char Dx = *(unsigned char *)X;
	unsigned char Dy = *(unsigned char *)Y;
	if (Dx < Dy) return -1;
	else if (Dx > Dy) return 1;
	else return 0;
}

void MedianBlur3X3_Ori(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride) {
	int Channel = Stride / Width;
	if (Channel == 1) {
		unsigned char Array[9];
		for (int Y = 1; Y < Height - 1; Y++) {
			unsigned char *LineP0 = Src + (Y - 1) * Stride + 1;
			unsigned char *LineP1 = LineP0 + Stride;
			unsigned char *LineP2 = LineP1 + Stride;
			unsigned char *LinePD = Dest + Y * Stride + 1;
			for (int X = 1; X < Width - 1; X++) {
				Array[0] = LineP0[X - 1];        Array[1] = LineP0[X];    Array[2] = LineP0[X + 1];
				Array[3] = LineP1[X - 1];        Array[4] = LineP1[X];    Array[5] = LineP2[X + 1];
				Array[6] = LineP2[X - 1];        Array[7] = LineP2[X];    Array[8] = LineP2[X + 1];
				qsort(Array, 9, sizeof(unsigned char), &ComparisonFunction);
				LinePD[X] = Array[4];
			}
		}
	}
	else {
		unsigned char ArrayB[9], ArrayG[9], ArrayR[9];
		for (int Y = 1; Y < Height - 1; Y++) {
			unsigned char *LineP0 = Src + (Y - 1) * Stride + 3;
			unsigned char *LineP1 = LineP0 + Stride;
			unsigned char *LineP2 = LineP1 + Stride;
			unsigned char *LinePD = Dest + Y * Stride + 3;
			for (int X = 1; X < Width - 1; X++){
				ArrayB[0] = LineP0[-3];       ArrayG[0] = LineP0[-2];       ArrayR[0] = LineP0[-1];
				ArrayB[1] = LineP0[0];        ArrayG[1] = LineP0[1];        ArrayR[1] = LineP0[2];
				ArrayB[2] = LineP0[3];        ArrayG[2] = LineP0[4];        ArrayR[2] = LineP0[5];

				ArrayB[3] = LineP1[-3];       ArrayG[3] = LineP1[-2];       ArrayR[3] = LineP1[-1];
				ArrayB[4] = LineP1[0];        ArrayG[4] = LineP1[1];        ArrayR[4] = LineP1[2];
				ArrayB[5] = LineP1[3];        ArrayG[5] = LineP1[4];        ArrayR[5] = LineP1[5];

				ArrayB[6] = LineP2[-3];       ArrayG[6] = LineP2[-2];       ArrayR[6] = LineP2[-1];
				ArrayB[7] = LineP2[0];        ArrayG[7] = LineP2[1];        ArrayR[7] = LineP2[2];
				ArrayB[8] = LineP2[3];        ArrayG[8] = LineP2[4];        ArrayR[8] = LineP2[5];

				qsort(ArrayB, 9, sizeof(unsigned char), &ComparisonFunction);
				qsort(ArrayG, 9, sizeof(unsigned char), &ComparisonFunction);
				qsort(ArrayR, 9, sizeof(unsigned char), &ComparisonFunction);

				LinePD[0] = ArrayB[4];
				LinePD[1] = ArrayG[4];
				LinePD[2] = ArrayR[4];

				LineP0 += 3;
				LineP1 += 3;
				LineP2 += 3;
				LinePD += 3;
			}
		}
	}
}

朴素算法的改进

由于排序耗时是非常多的,而这里实际上就是在9个元素中找到中位数,这个实际上是不需要排序就可以办到的,只要我们按照下面的方法进行比较就可以获得中位数。实际上只需要19次比较,我们先看源码:

void Swap(int &X, int &Y) {
	X ^= Y;
	Y ^= X;
	X ^= Y;
}

void MedianBlur3X3_Faster(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride){
	int Channel = Stride / Width;
	if (Channel == 1){

		for (int Y = 1; Y < Height - 1; Y++){
			unsigned char *LineP0 = Src + (Y - 1) * Stride + 1;
			unsigned char *LineP1 = LineP0 + Stride;
			unsigned char *LineP2 = LineP1 + Stride;
			unsigned char *LinePD = Dest + Y * Stride + 1;
			for (int X = 1; X < Width - 1; X++){
				int Gray0, Gray1, Gray2, Gray3, Gray4, Gray5, Gray6, Gray7, Gray8;
				Gray0 = LineP0[X - 1];        Gray1 = LineP0[X];    Gray2 = LineP0[X + 1];
				Gray3 = LineP1[X - 1];        Gray4 = LineP1[X];    Gray5 = LineP2[X + 1];
				Gray6 = LineP2[X - 1];        Gray7 = LineP2[X];    Gray8 = LineP2[X + 1];

				if (Gray1 > Gray2) Swap(Gray1, Gray2);
				if (Gray4 > Gray5) Swap(Gray4, Gray5);
				if (Gray7 > Gray8) Swap(Gray7, Gray8);
				if (Gray0 > Gray1) Swap(Gray0, Gray1);
				if (Gray3 > Gray4) Swap(Gray3, Gray4);
				if (Gray6 > Gray7) Swap(Gray6, Gray7);
				if (Gray1 > Gray2) Swap(Gray1, Gray2);
				if (Gray4 > Gray5) Swap(Gray4, Gray5);
				if (Gray7 > Gray8) Swap(Gray7, Gray8);
				if (Gray0 > Gray3) Swap(Gray0, Gray3);
				if (Gray5 > Gray8) Swap(Gray5, Gray8);
				if (Gray4 > Gray7) Swap(Gray4, Gray7);
				if (Gray3 > Gray6) Swap(Gray3, Gray6);
				if (Gray1 > Gray4) Swap(Gray1, Gray4);
				if (Gray2 > Gray5) Swap(Gray2, Gray5);
				if (Gray4 > Gray7) Swap(Gray4, Gray7);
				if (Gray4 > Gray2) Swap(Gray4, Gray2);
				if (Gray6 > Gray4) Swap(Gray6, Gray4);
				if (Gray4 > Gray2) Swap(Gray4, Gray2);

				LinePD[X] = Gray4;
			}
		}

	}
	else{
		for (int Y = 1; Y < Height - 1; Y++){
			unsigned char *LineP0 = Src + (Y - 1) * Stride + 3;
			unsigned char *LineP1 = LineP0 + Stride;
			unsigned char *LineP2 = LineP1 + Stride;
			unsigned char *LinePD = Dest + Y * Stride + 3;
			for (int X = 1; X < Width - 1; X++){
				int Blue0, Blue1, Blue2, Blue3, Blue4, Blue5, Blue6, Blue7, Blue8;
				int Green0, Green1, Green2, Green3, Green4, Green5, Green6, Green7, Green8;
				int Red0, Red1, Red2, Red3, Red4, Red5, Red6, Red7, Red8;
				Blue0 = LineP0[-3];        Green0 = LineP0[-2];    Red0 = LineP0[-1];
				Blue1 = LineP0[0];        Green1 = LineP0[1];        Red1 = LineP0[2];
				Blue2 = LineP0[3];        Green2 = LineP0[4];        Red2 = LineP0[5];

				Blue3 = LineP1[-3];        Green3 = LineP1[-2];    Red3 = LineP1[-1];
				Blue4 = LineP1[0];        Green4 = LineP1[1];        Red4 = LineP1[2];
				Blue5 = LineP1[3];        Green5 = LineP1[4];        Red5 = LineP1[5];

				Blue6 = LineP2[-3];        Green6 = LineP2[-2];    Red6 = LineP2[-1];
				Blue7 = LineP2[0];        Green7 = LineP2[1];        Red7 = LineP2[2];
				Blue8 = LineP2[3];        Green8 = LineP2[4];        Red8 = LineP2[5];

				if (Blue1 > Blue2) Swap(Blue1, Blue2);
				if (Blue4 > Blue5) Swap(Blue4, Blue5);
				if (Blue7 > Blue8) Swap(Blue7, Blue8);
				if (Blue0 > Blue1) Swap(Blue0, Blue1);
				if (Blue3 > Blue4) Swap(Blue3, Blue4);
				if (Blue6 > Blue7) Swap(Blue6, Blue7);
				if (Blue1 > Blue2) Swap(Blue1, Blue2);
				if (Blue4 > Blue5) Swap(Blue4, Blue5);
				if (Blue7 > Blue8) Swap(Blue7, Blue8);
				if (Blue0 > Blue3) Swap(Blue0, Blue3);
				if (Blue5 > Blue8) Swap(Blue5, Blue8);
				if (Blue4 > Blue7) Swap(Blue4, Blue7);
				if (Blue3 > Blue6) Swap(Blue3, Blue6);
				if (Blue1 > Blue4) Swap(Blue1, Blue4);
				if (Blue2 > Blue5) Swap(Blue2, Blue5);
				if (Blue4 > Blue7) Swap(Blue4, Blue7);
				if (Blue4 > Blue2) Swap(Blue4, Blue2);
				if (Blue6 > Blue4) Swap(Blue6, Blue4);
				if (Blue4 > Blue2) Swap(Blue4, Blue2);

				if (Green1 > Green2) Swap(Green1, Green2);
				if (Green4 > Green5) Swap(Green4, Green5);
				if (Green7 > Green8) Swap(Green7, Green8);
				if (Green0 > Green1) Swap(Green0, Green1);
				if (Green3 > Green4) Swap(Green3, Green4);
				if (Green6 > Green7) Swap(Green6, Green7);
				if (Green1 > Green2) Swap(Green1, Green2);
				if (Green4 > Green5) Swap(Green4, Green5);
				if (Green7 > Green8) Swap(Green7, Green8);
				if (Green0 > Green3) Swap(Green0, Green3);
				if (Green5 > Green8) Swap(Green5, Green8);
				if (Green4 > Green7) Swap(Green4, Green7);
				if (Green3 > Green6) Swap(Green3, Green6);
				if (Green1 > Green4) Swap(Green1, Green4);
				if (Green2 > Green5) Swap(Green2, Green5);
				if (Green4 > Green7) Swap(Green4, Green7);
				if (Green4 > Green2) Swap(Green4, Green2);
				if (Green6 > Green4) Swap(Green6, Green4);
				if (Green4 > Green2) Swap(Green4, Green2);

				if (Red1 > Red2) Swap(Red1, Red2);
				if (Red4 > Red5) Swap(Red4, Red5);
				if (Red7 > Red8) Swap(Red7, Red8);
				if (Red0 > Red1) Swap(Red0, Red1);
				if (Red3 > Red4) Swap(Red3, Red4);
				if (Red6 > Red7) Swap(Red6, Red7);
				if (Red1 > Red2) Swap(Red1, Red2);
				if (Red4 > Red5) Swap(Red4, Red5);
				if (Red7 > Red8) Swap(Red7, Red8);
				if (Red0 > Red3) Swap(Red0, Red3);
				if (Red5 > Red8) Swap(Red5, Red8);
				if (Red4 > Red7) Swap(Red4, Red7);
				if (Red3 > Red6) Swap(Red3, Red6);
				if (Red1 > Red4) Swap(Red1, Red4);
				if (Red2 > Red5) Swap(Red2, Red5);
				if (Red4 > Red7) Swap(Red4, Red7);
				if (Red4 > Red2) Swap(Red4, Red2);
				if (Red6 > Red4) Swap(Red6, Red4);
				if (Red4 > Red2) Swap(Red4, Red2);

				LinePD[0] = Blue4;
				LinePD[1] = Green4;
				LinePD[2] = Red4;

				LineP0 += 3;
				LineP1 += 3;
				LineP2 += 3;
				LinePD += 3;
			}
		}
	}
}

为了帮助理解我画了一张图:
在这里插入图片描述只画了前6个指令,随着比较的不断执行,最后最小的4个数会排在前4个位置,最大的4个数会排在后4个位置,中位数恰好就在中间。对于24位图原理是一样的。这个算法的流水情况比第一个算法好多了,自然也会得到较大的速度提升。

SSE优化

这个地方是本文的重点了,根据ImageShop博主所说,从 https://github.com/ARM-software/ComputeLibrary/blob/master/src/core/NEON/kernels/NEMedian3x3Kernel.cpp#L113 这段代码可以获悉,每个像素的9次比较虽然不能直接用SIMD指令来做,但是多个像素的比较是不想关的(这个地方需要思考为什么不相关,因为我们比较的时候交换是使用临时变量,实际上是没有改变每个位置的像素的位置的)。所以SSE优化的思路就有了,现在可以一次性处理16个像素了。代码如下:

void MedianBlur3X3_Fastest(unsigned char *Src, unsigned char *Dest, int Width, int Height, int Stride) {
	int Channel = Stride / Width;
	int BlockSize = 16, Block = ((Width - 2)* Channel) / BlockSize;
	for (int Y = 1; Y < Height - 1; Y++){
		unsigned char *LineP0 = Src + (Y - 1) * Stride + Channel;
		unsigned char *LineP1 = LineP0 + Stride;
		unsigned char *LineP2 = LineP1 + Stride;
		unsigned char *LinePD = Dest + Y * Stride + Channel;
		for (int X = 0; X < Block * BlockSize; X += BlockSize, LineP0 += BlockSize, LineP1 += BlockSize, LineP2 += BlockSize, LinePD += BlockSize)
		{
			__m128i P0 = _mm_loadu_si128((__m128i *)(LineP0 - Channel));
			__m128i P1 = _mm_loadu_si128((__m128i *)(LineP0 - 0));
			__m128i P2 = _mm_loadu_si128((__m128i *)(LineP0 + Channel));
			__m128i P3 = _mm_loadu_si128((__m128i *)(LineP1 - Channel));
			__m128i P4 = _mm_loadu_si128((__m128i *)(LineP1 - 0));
			__m128i P5 = _mm_loadu_si128((__m128i *)(LineP1 + Channel));
			__m128i P6 = _mm_loadu_si128((__m128i *)(LineP2 - Channel));
			__m128i P7 = _mm_loadu_si128((__m128i *)(LineP2 - 0));
			__m128i P8 = _mm_loadu_si128((__m128i *)(LineP2 + Channel));

			_mm_sort_ab(P1, P2);		_mm_sort_ab(P4, P5);		_mm_sort_ab(P7, P8);
			_mm_sort_ab(P0, P1);		_mm_sort_ab(P3, P4);		_mm_sort_ab(P6, P7);
			_mm_sort_ab(P1, P2);		_mm_sort_ab(P4, P5);		_mm_sort_ab(P7, P8);
			_mm_sort_ab(P0, P3);		_mm_sort_ab(P5, P8);		_mm_sort_ab(P4, P7);
			_mm_sort_ab(P3, P6);		_mm_sort_ab(P1, P4);		_mm_sort_ab(P2, P5);
			_mm_sort_ab(P4, P7);		_mm_sort_ab(P4, P2);		_mm_sort_ab(P6, P4);
			_mm_sort_ab(P4, P2);

			_mm_storeu_si128((__m128i *)LinePD, P4);
		}
		
		for (int X = Block * BlockSize; X < (Width - 2) * Channel; X++, LinePD++){
			int Gray0, Gray1, Gray2, Gray3, Gray4, Gray5, Gray6, Gray7, Gray8;
			Gray0 = LineP0[X - Block * BlockSize - Channel];        Gray1 = LineP0[X - Block * BlockSize];    Gray2 = LineP0[X - Block * BlockSize + Channel];
			Gray3 = LineP1[X - Block * BlockSize - Channel];        Gray4 = LineP1[X - Block * BlockSize];    Gray5 = LineP1[X - Block * BlockSize + Channel];
			Gray6 = LineP2[X - Block * BlockSize - Channel];        Gray7 = LineP2[X - Block * BlockSize];    Gray8 = LineP2[X - Block * BlockSize + Channel];

			if (Gray1 > Gray2) Swap(Gray1, Gray2);
			if (Gray4 > Gray5) Swap(Gray4, Gray5);
			if (Gray7 > Gray8) Swap(Gray7, Gray8);
			if (Gray0 > Gray1) Swap(Gray0, Gray1);
			if (Gray3 > Gray4) Swap(Gray3, Gray4);
			if (Gray6 > Gray7) Swap(Gray6, Gray7);
			if (Gray1 > Gray2) Swap(Gray1, Gray2);
			if (Gray4 > Gray5) Swap(Gray4, Gray5);
			if (Gray7 > Gray8) Swap(Gray7, Gray8);
			if (Gray0 > Gray3) Swap(Gray0, Gray3);
			if (Gray5 > Gray8) Swap(Gray5, Gray8);
			if (Gray4 > Gray7) Swap(Gray4, Gray7);
			if (Gray3 > Gray6) Swap(Gray3, Gray6);
			if (Gray1 > Gray4) Swap(Gray1, Gray4);
			if (Gray2 > Gray5) Swap(Gray2, Gray5);
			if (Gray4 > Gray7) Swap(Gray4, Gray7);
			if (Gray4 > Gray2) Swap(Gray4, Gray2);
			if (Gray6 > Gray4) Swap(Gray6, Gray4);
			if (Gray4 > Gray2) Swap(Gray4, Gray2);

			LinePD[X] = Gray4;
			LineP0 += 1;
			LineP1 += 1;
			LineP2 += 1;
		}
	}
}

速度测试结果

在这里插入图片描述

参考博客

https://www.cnblogs.com/Imageshop/p/11087804.html

源码获取

https://github.com/BBuf/Image-processing-algorithm-Speed/blob/master/speed_median_filter_3x3_sse.cpp

OpenCV算法加速的一些学习总结 Opencv算子加速 TBB、SSE、OpenMP、AVX加速学习总结 阅读详情

相关推荐

中值滤波算法与SSE2指令集并行优化

中值滤波算法是经典图像处理中极为常见的操作,一般我们通过调用OpenCV或者是Matlab直接进行使用,以至于有种它本来就很容易实现且速度很快的错觉。近来用到中值滤波算法,因为不想用到OpenCV库或者Matlab而对其实现研究了一番,才发现其中有很多值得注意的细节。下面我们结合着OpenCV的源码实现来讲。

weixinhum 404

cv::Mat 快速遍历与快速中值滤波

1.图像快速遍历 遍历方法:直接获取cv::Mat对象的像素块数据指针 void fasterTraversePixel(cv::Mat &src) { int w = src.cols; int h = src.rows; for (int row = 0; row < h; row++) { uchar* uc_pixel = src.data + row*s...

qq_25349629的博客 1121

中值滤波和快速中值滤波算法源代码(含图像显示和打开,且可计时比较)

经典的中值滤波算法要求对窗口内的像素进行排序,当窗口尺寸较大时,处理速度很慢,不能满足计算机对图像处理的实时性要求。本文探讨了中值滤波的快速算法,旨在提高中值滤波处理速度。结果表明,快速算法可是处理时间大大减小。

任意半径中值滤波(扩展至百分比滤波器)O(1)时间复杂度算法的原理、实现及效果。...

     主要参考论文:Median Filter in Constant Time.pdf     参考代码:http://files.cnblogs.com/Imageshop/CTMF.rar     中值滤波是一种经典的图像操作,特别适用于椒盐噪音的去除。同样,他也是USM锐化(表示怀疑,我记得是高斯滤波)、顺序处理、形态学操作(比如去孤点)等算法的基础。更高级别的应用包括目标分割、语...

weixin_33901641的博客 399

cuda实现的中值滤波介绍

高性能并行运算已经成为图像处理不可缺少的利器,越来越多的人开始使用cuda去加速自己的程序,本文采用cuda来加速中值滤波器的处理。取得了很好地效果。

MMX和SSE实现的opencv数据结构的图像反色算法优化

利用MMX和SSE实现的opencv的Mat类型的图像发色算法优化,可以作为MMX和SSE算法优化的入门例程

数字图像处理——中值滤波及其改进算法

中值滤波器是非线性滤波器的一个例子,它在保留图像特征方面非常有效。 但是,滤波器的窗口大小直接影响中值滤波器的性能。 较小的窗口保留了特征,但会导致噪声抑制的减少。 在较大窗口的情况下,噪声抑制很高,但图像内容保留有限。 随着对标准中值滤波器的研究,提出了许多滤波器,如加权中值滤波器和许多其他高级滤波器。

沧海一升的博客 8020

计算机视觉_图像处理_SSE指令集优化_OpenCV加速框架_局部直方图算法_中值滤波_最大值滤波_最小值滤波_表面模糊处理_RGB转灰度_自然饱和度增强_Sobel边缘检测_肤色检测_多线程.zip

计算机视觉_图像处理_SSE指令集优化_OpenCV加速框架_局部直方图算法_中值滤波_最大值滤波_最小值滤波_表面模糊处理_RGB转灰度_自然饱和度增强_Sobel边缘检测_肤色检测_多线程.zip

SSE图像算法优化系列十九:一种局部Gamma校正对比度增强算法及其SSE优化。

  这是一篇2010年比较古老的文章了,是在QQ群里一位群友提到的,无聊下载看了下,其实也没有啥高深的理论,抽空实现了下,虽然不高大上,还是花了点时间和心思优化了代码,既然这样,就顺便分享下优化的思路和经历。   文章的名字为:Contrast image correction method,由于本人博客的后台文件已经快超过博客园所容许的最大空间,这里就不直接上传文章了,大家可以直接点我提供的链...

PixelDemon的博客 411

基于C++的图像处理算法实现、INTEL上SSE加速、ARM上NEON加速

图像处理算法实现、INTEL上SSE加速、ARM上NEON加速 1.常用图像处理算子实现 2.常用图像处理算子基于Arm 指令集Neon的实现 3.常用图像处理算子基于intel 指令集SSE的实现

CSR mascon产品深度解析

GRACE数据产品 mascon产品 质量变化 地球重力场

weixin_43047707的博客 4432

sse性能提升多少倍_从 CNN 性能优化说起(二)

书接上文 从 CNN 性能优化说起(一)。上回说到贾杨清把 convolution 转化为矩阵乘。这个方法在图像领域曾经有人用过。扬清的 memo 里提到 MATLAB 里有一个操作 im2col 就是干这个的。不过在深度学习领域,扬清是第一个用这个方法加速 CNN 的。那么矩阵乘应该怎么优化呢?这里用到的思路是通用的。在计算机专业本科的《计算机体系结构》里都有介绍的。优化数据库执行引擎、互联网后...

weixin_39550486的博客 451

CentOS7 安装天气分型软件cost733过程详解

cost733是一款天气分型软件,其内置的一些算法可以帮助气象工作者进行天气类型划分等(我也是初学者,仅仅知道一些皮毛),但是网上找到的安装办法比较少,并且总会出现一些报错,试了一晚上,终于将安装办法调通了,希望可以帮助到大家

weixin_62573024的博客 3561

SSE图像算法优化系列2-高斯滤波

前言 本算法的原理以及优化过程都是偷师ImageShop,也可以把这篇文章理解为https://www.cnblogs.com/Imageshop/p/6376028.html 这篇文章的一篇阅读总结。 原理 首先,高斯滤波是可以用递归算法来实现的。这最早见于《Recursive implementation of the Gaussian filter》论文中: 在forward的过程中,n是递...

I good vegetable a! 3047

基于Web的智能家居(源码+开题)

实践上,智能家居系统的普及和应用将极大改善人们的居住体验,提高生活质量,同时也有助于促进智能家居产业链的发展和完善,为社会经济发展注入新的活力。此外,本研究还将对基于Web的智能家居系统的用户体验进行深入研究,通过用户调研和数据分析,不断优化系统功能和界面设计,提升用户的使用体验和满意度。针对以上问题,本研究将综合运用物联网、云计算、大数据等新一代信息技术,通过系统架构设计、功能模块开发、安全性保障、用户体验优化等多个方面的研究工作,力求为基于Web的智能家居系统的研发和应用提供全面而有效的解决方案。

sryue06的博客 1902

BSW:MemMap模块配置及使用

(内存映射(MemMap)模块用于通过内存映射文件将代码和数据映射到特定的内存部分。MemMap生成特定的头文件,其中包含为MemorySection元素和编译器特定指令定义的内存映射预处理器。上面是比较官方的回答,说人话就是把数据和代码放在ECU内指定的地址。初级应用:软件中的bss,data,rodata,code,text,段需要在memory layout中划分具体的物理地址,对于多核系统,要将执行的数据和代码放在目标核的RAM和ROM。

Forever_Oct的博客 3673

并行加速实战 双边滤波器

之前分析了 二维中值滤波器的并行加速 由于二维中值滤波器是控制密集型的滤波器(排序操作),所以SSE加速不太明显 这次选用了计算密集型的双边滤波器 针对双边滤波器在5*5的滤波核下的运算速度做优化和分析 以下会有主区域、全图、主循环、完整(初始化+主循环)的概念 1.     由于双边滤波的滤波半径为2+1,所以不能忽略图像四周边界的区域了。 所以,以下会对主区

billbliss的专栏 2544

别再手动切换了!用SP3485+三极管搞定RS485自动收发电路(附完整原理图)

本文详细介绍了如何利用SP3485芯片和三极管设计RS485自动收发电路,解决传统手动切换带来的IO资源占用和软件复杂度问题。通过原理分析、电路设计拆解和实战注意事项,帮助工程师打造稳定可靠的自动收发通信模块,显著提升系统性能和可靠性。

weixin_26833939的博客 509

中值滤波中位数优化算法

class MidSort(private val SIZE:Int=251) { private var index = 0 private var medIndex=SIZE shr 1 private val data=IntArray(SIZE) private val dataFlag=BooleanArray(SIZE){ it<medIndex } private var medValue = 0 fun init.

711

Origin教程004:Origin图形导出

需要编辑的话,双击图形,会自动用origin软件打开图形,这种方式是最开始导出图形的功能,方式一和二都是后面增加的。如果导出的图片边距较大的时候,会影响图片的美观,可以通过。也可以设置在PPT中直接编辑,找到。解决方法是,选择一条线,

WwLK123的博客 6327

在ABAQUS中使用VUMAT子程序实现Hashin失效准则的详细解析与实践:深入探讨复合材料模拟仿真的高级编程技巧

Hashin失效准则是由材料科学家Shlomo Hashin于1962年提出的一种基于能量方法的多向失效理论,主要用于预测复合材料的破坏行为。与传统的单向失效理论不同,Hashin准则考虑了材料内部的多种独立破坏机制,如基体断裂、界面脱粘、纤维断裂等,这些机制在不同应力状态下可能同时或分别发生。通过计算各个机制的能量释放率,Hashin失效准则能够更为准确地预测复合材料在复杂应力状态下的破坏行为。

qq_38334677的博客 1948

【AI PC端算法优化】八,小半径中值滤波的SSE极速优化

1. 前言 大家应该经常碰到这种需求,那就是使用3×33\times 33×3或者5×55\times 55×5这种相对比较小的窗口进行中值滤波,而如果在图像的分辨率比较大的情况下这种操作也是比较耗时的。所以在这种固定场景下设计一个定制的优化算法是有意义的。 2. 普通的3*3中值滤波实现 普通的实现没什么好说,就是直接在窗口区域内遍历寻找中位数即可,这里获取中值直接使用了c语言的qsort。代码实现如下: int ComparisonFunction(const void *X, const void *

I good vegetable a! 1046

20、认知负荷理论在教育技术中的应用

本文深入探讨了认知负荷理论(Cognitive Load Theory, CLT)在教育技术中的应用,重点分析了如何通过优化教学设计减少学习者的认知负荷,提高学习效率。文章介绍了认知负荷的三种类型:内在认知负荷、外在认知负荷和germane认知负荷,并结合多媒体学习原则(如模态效应、空间连续性原则、时间连续性原则等)提出了减少外在认知负荷的具体策略。此外,文章通过实证研究和教学案例,展示了认知负荷理论在不同学科和个性化教学中的广泛应用和有效性。最终,文章总结了应用认知负荷理论进行教学设计的具体流程,强调其在

solidity8miner的博客 922

SSE算法优化系列六:使用SSE优化最大值滤波

前言

I good vegetable a! 2165

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

图像处理:中值滤波&均值滤波

转自:openCV之中值滤波&amp;均值滤波(及代码实现):https://blog.csdn.net/weixin_37720172/article/details/72627543  在开始我们今天的博客之前,我们需要先了解一下什么是滤波: openCV之中值滤波&amp;均值滤波(及代码实现)首先我们看一下图像滤波的概念。图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑...

qinghuaci666的博客 22万+

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

中值滤波

1、基本原理图像的中值滤波是一种非线性图像处理方法,是统计排序滤波器的一种典型应用。与之前介绍的均值处理的思想有所不同,中值滤波是通过对邻域内像素按灰度排序的结果决定中心像素的灰度。具体的操作过程如下:用一个奇数点的移动窗口,将窗口中心点的值用窗口内各点的中值代替。假设窗口内有5个点,其值为1,2,3,4和5,那么此窗口内各点的中值即为3,也就是用3来代替中心点的像素值。中值滤波对于滤除脉冲干扰及...

harry的博客 5万+

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

上一篇: SSE优化系列八:使用SSE优化多尺度细节提升算法
下一篇: Tensorflow实战10:Tensorflow实现Word2Vec
just_sort
博客等级 码龄11年 2356粉丝 1667原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值