Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【短道速滑十一】标准的Gabor滤波器及Log_Gabor滤波器的实现、解析、速度优化及其和Halcon中gen_gabor的比较。

【短道速滑十一】标准的Gabor滤波器及Log_Gabor滤波器的实现、解析、速度优化及其和Halcon中gen_gabor的比较。

作者头像
用户1138785
发布于 2023-10-23 11:19:06
发布于 2023-10-23 11:19:06
53300
代码可运行
举报
运行总次数:0
代码可运行

  最近有朋友在研究Halcon中gen_gabor的函数,和我探讨,因为我之前也没有怎么去关注这个函数,因此,前前后后大概也折腾了有一个星期去模拟实现这个东西,虽然最终没有实现这个函数,但是也是有所收获,这里做一点总结,也算是最这个函数有个完美的收尾吧。

  1、Gabor滤波器

  首先总是度娘出场,关键词Gabor滤波器,一大堆东西出来了,里面最多的肯定是关于OpenCv的getGaborKernel函数,这个函数的具体代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
 Gabor filters and such. To be greatly extended to have full texture analysis.
 For the formulas and the explanation of the parameters see:
 http://en.wikipedia.org/wiki/Gabor_filter
*/
cv::Mat cv::getGaborKernel( Size ksize, double sigma, double theta,
                            double lambd, double gamma, double psi, int ktype )
{
    double sigma_x = sigma;
    double sigma_y = sigma/gamma;
    int nstds = 3;
    int xmin, xmax, ymin, ymax;
    double c = cos(theta), s = sin(theta);
    if( ksize.width > 0 )
        xmax = ksize.width/2;
    else
        xmax = cvRound(std::max(fabs(nstds*sigma_x*c), fabs(nstds*sigma_y*s)));

    if( ksize.height > 0 )
        ymax = ksize.height/2;
    else
        ymax = cvRound(std::max(fabs(nstds*sigma_x*s), fabs(nstds*sigma_y*c)));

    xmin = -xmax;
    ymin = -ymax;
    CV_Assert( ktype == CV_32F || ktype == CV_64F );
    Mat kernel(ymax - ymin + 1, xmax - xmin + 1, ktype);
    double scale = 1;
    double ex = -0.5/(sigma_x*sigma_x);
    double ey = -0.5/(sigma_y*sigma_y);
    double cscale = CV_PI*2/lambd;
    for( int y = ymin; y <= ymax; y++ )
        for( int x = xmin; x <= xmax; x++ )
        {
            double xr = x*c + y*s;
            double yr = -x*s + y*c;

            double v = scale*std::exp(ex*xr*xr + ey*yr*yr)*cos(cscale*xr + psi);
            if( ktype == CV_32F )
                kernel.at<float>(ymax - y, xmax - x) = (float)v;
            else
                kernel.at<double>(ymax - y, xmax - x) = v;
        }
    return kernel;
}

  可以快速看出,这段代码仅仅是根据一些参数计算出一个卷积核,具体的公式我也没怎么关注,里面有个nstds 这个常量为3,这个只在用户输入的ksize尺寸为0的时候需要用到,感觉是和高斯核函数在半径大于3*Sigma后其对结果的贡献就可以忽略不计有关。 

  这个函数生成的卷积核的形状和参数之间的关系,很多文章都有探讨,这个不是本文的重点,比如下面这个链接:https://blog.csdn.net/Wslsdx/article/details/110728050

  基本上,在空域他的形状就是一些有间隔的白色过度条,在频域,则基本为两处白色亮点,如下图所示:

      卷积核空域图形化               对应的频域图

  通常,CV的getGaborKernel函数都要配合Filter2D函数进行卷积得到想要的结果。 

  网络上一个有意思的视觉效果方面的算法在https://zhuanlan.zhihu.com/p/584907623有提到,可以用这个滤波器来做一些特效。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static std::vector<cv::Mat> build_filters()
{
    std::vector<cv::Mat> filters;
    const int ksize = 31;
    const double sigma = 4.0;
    const double lambd = 10.0;
    const double gamma = 0.5;
    const double psi = 0;
    // 此处创建16个滤波器, 只有 getGaborkernel 的第三个参数 theta 不同
    for (int i = 0; i < 16; i++)
    {
        double theta = CV_PI * i / 16;
        cv::Mat kernel = cv::getGaborKernel(cv::Size(ksize, ksize), sigma, theta, lambd, gamma, psi, CV_32F);
        kernel /= 1.5 * cv::sum(kernel)[0];
        filters.emplace_back(kernel);
    }
    return filters;
}
cv::Mat process(const cv::Mat& src, std::vector<cv::Mat>& filters)
{
    cv::Mat accum = cv::Mat::zeros(src.size(), src.type());
    for (cv::Mat kernel: filters)
    {
        cv::Mat fimg;
        AutoTimer timer("filter2D");
        cv::filter2D(src, fimg, CV_8UC3, kernel); // 这里是耗时的瓶颈
        AutoTimer timer("getmax");
        accum = cv::max(accum, fimg);
    }
    return accum;
}
int main()
{
    cv::Mat src = cv::imread(image_path);
    std::vector<cv::Mat> filters = build_filters();
    cv::Mat res = process(src, filters);
}

 、

  这里用了16个滤波器组合求最大值,得到了一种特征线条凸出的效果。 

  当然,OpenCv的这个滤波器在一些特征识别方面也有着很大的作用,比如斑马线识别等等。

  但是,测试发现这个滤波器对参数的配置极其敏感,同一个参数,一般两个值如果只相差一点点,一般出来的效果不会有太大的区别,但是这个函数,确可能会出现极大的差异。比如波长这个参数,当为0.4和0.5的结果大相径庭。  

                波长为0.4时的结果                                                    波长为0.5时的结果

  仔细的分析这个问题,我们会发现,这个还是由于当参数改变时,这个滤波器的权重会出现波动,一般这些卷积核都需要归一化或做相关处理,当波长为0.5时,我们会发现归一化时,所有滤波器的和可能为负数或者很小的数,而为0.4时则较为正常。因此,出现了参数改变一点点,结果改变一大串的问题。

  再稍微撤远一点,当我自己实现这个函数时,我们会发现他的主要耗时还是Filter2D函数,关于这个函数,OpenCV内部是做了优化的,他会根据硬件的支持情况使用opencl/ipp等加速资源实现,速度是相当的快,而且也会对核的大小做判断,很小的核不会使用FFT。  我这里直接使用FFT做的实现,虽然我在进行FFT卷积时做了很多优化,比如拆解为多个256*256的FFT, 比如充分利用虚部的数据等等,结果还是干不过Opencv的速度。

  二、LogGabor滤波器

  拿OpenCv的Gabor滤波器和Halcon的gen_gabor相比,发现他们根本不是一回事,gen_gabor直接生成了频域的数据,而不是生成了卷积核。关于这个算子,我们发现halcon里的描述也不是特别的清晰,这有点不太像他的风格。

  百度搜索gen_gabor我们能发现的99%的资料都是halcon帮助文档的英文原版或者是相关翻译,基本没有对其进行原理进行描述。可能也是因为这个算子不是很常用的原因吧。

  在搜索Gabor滤波器时,也看到了一些文章讲LogGabor滤波器,其中有一篇文章有提到 Log-Gabor函数并不能在空间域中得到表达式,滤波器的构造须在频域中进行,这个和gen_gabor的描述非常相似。后面我们对其参数进行了一些分析,基本可以确定halcon的gabor应该是类似于LogGabor滤波器之类的。

  通过搜索LogGabor,我们得到了一下几个比较有用的参考链接和代码:

Python OpenCV实现Log Gabor滤波器(由LGHD描述符扩展) 以及 Github中一篇 PhaseCongruency/gaborconvolve.m的matlab代码

  还有一个非常有用的图片:

  通过阅读这几篇文章及其配套的代码,我们发现这个频域的滤波器可由Log-Radial Gaussian和Angular Gaussian组合而成,在Python那篇文章中,则有这更为明确的公式:

  原文描述如下:

      一个二维的L-Gaborj波器可以分解为径向滤波器和角度滤波器两部分,对应极坐标公式为:

      完整的Log-Gabor滤波器由这两部分相乘得到:

  这个公式也和上面的图片能完全对应。

  在代码实现上,我发现无损是Python的代码还是matlab的代码其实都是一个版本的,他们在计算有关的过程中都有一个lowpass的过程,我不清楚那个是目的是啥,也不知道哪里的参数来源依据是什么,但是我感觉他们不应该是我所需要的,我需要的就是上面两个公式,结合那些参考代码,我们对第一个公式(径向滤波器)的M代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
WaveLength = 10;
SigmaR = 0.4;
cols = 500, rows=500;
[x,y] = meshgrid( [-cols/2:(cols/2-1)]/cols,[-rows/2:(rows/2-1)]/rows);
radius = sqrt(x.^2 + y.^2);       
Frequency = 1.0 / WaveLength;                  % 频率等于波长的导数
logGabor = exp((-(log(radius / Frequency)).^2) / (2 * SigmaR * SigmaR));  % log gabor函数的传递函数表达式
imshow(logGabor,[])

  对第二个公式的实现代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Angle = 45 / 180 *3.1415926;
SigmaA = 0.4;
cols = 500, rows=500;
[x,y] = meshgrid( [-cols/2:(cols/2-1)]/cols,[-rows/2:(rows/2-1)]/rows);
theta = atan2(-y,x);              
sintheta = sin(theta);
costheta = cos(theta);
ds = sintheta * cos(Angle) - costheta * sin(Angle);    
dc = costheta * cos(Angle) + sintheta * sin(Angle);     
dtheta = atan2(abs(ds),abs(dc));                           
spread = exp((-dtheta.^2) / (2 * SigmaA * SigmaA));      
imshow(spread,[])

  当将两者组合起来后,即产生如下的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
WaveLength = 10;
SigmaR = 0.4;
Angle = 45 / 180 *3.1415926;
SigmaA = 0.4;
cols = 500, rows=500;
[x,y] = meshgrid( [-cols/2:(cols/2-1)]/cols,[-rows/2:(rows/2-1)]/rows);
radius = sqrt(x.^2 + y.^2);  
Frequency = 1.0 / WaveLength;                  % 频率等于波长的导数
logGabor = exp((-(log(radius / Frequency)).^2) / (2 * SigmaR * SigmaR));  % log gabor函数的传递函数表达式
theta = atan2(-y,x);              
sintheta = sin(theta);
costheta = cos(theta);
ds = sintheta * cos(Angle) - costheta * sin(Angle);    
dc = costheta * cos(Angle) + sintheta * sin(Angle);     
dtheta = atan2(abs(ds),abs(dc));                           
spread = exp((-dtheta.^2) / (2 * SigmaA * SigmaA));      
imshow(logGabor .* spread,[])

  三段代码产生的图像依次如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
                                        WaveLength = 10,SigmaR = 0.4,Angle = 45 / 180 *3.1415926, SigmaA = 0.4;

  通过改变参数可以获得不同的效果,比如,WaveLength = 5,SigmaR = 0.05,Angle = 30 / 180 *3.1415926, SigmaA = 0.3时的效果如下:

  注意到,相比于原始的代码,我们在计算dtheta时,稍微做了修改,这是因为,频域的数据一般是要求堆成的,而原始的角向滤波器是非对称的,因此,我们改成了atan2(abs(ds),abs(dc));

  这个生成的过程里有很多浮点的计算,而且有几个复杂度比较高的函数,因此,计算还是有所耗时的。 

  我们来和halcon的gen_gabor的参数做下比较:

        gen_gabor( : ImageFilter : Angle, Frequency, Bandwidth, Orientation, Norm, Mode, Width, Height : )

  后面Norm, Mode, Width, Height 这四个参数不用管它,我们主要看看前面四个参数。 

  注意到我们刚才的代码里也提供了四个可选的参数,即WaveLength,SigmaR,Angle, SigmaA,那他们之间有么有什么对应的关系呢。 

  通过多次比较和测试,我们可以定性的确定如下联系:

  1、gen_gabor里的Orientation和我的LogGabor里的Angle基本是一个意思,这个可以从Orientation的范围可以看到,就是个角度范围:

     Orientation (input_control) real → (real)         Angle of the principal orientation,Suggested values: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.14

    2、gen_gabor的Bandwidth和LogGabor的SigmaR的趋势基本是一致的。

       3、gen_gabor的Frequency和LogGabor的WaveLength的趋势基本是相反的,但是WaveLength本身就是Frenquency的倒数,都是会随着Frequency的变小,频域的有效部分想中心收缩。

       4、gen_gabor的Angle和LogGabor的SigmaA的趋势基本是相反的。

  也就是说这4个参数基本上都存在一一对应的关系,只是说我们无法确认他们之间的绝对值之间的联系,毕竟halcon里也没有提供具体的计算式,只要稍微某个地方有些取值不同,就会造成不同的结果。 

  由于loggabor提供的已经是频域的数据了,因此,后续的计算就比较简单了,因为频域的乘法就相当于于时域的卷积,因此,直接把某个图像的频域数据乘以这个LogGabor数据就可以了。

       但是,这就要求LogGabor的数据维度必须和图像是一样大小的,其实这个有个隐藏的问题,即边缘问题,因为卷积对于边缘一般来说是需要扩展的,否则会遇到一些小小意料之外的问题。 

  做了一个简单的比较,当gen_gabor和LogGabor滤波器的可视化图基本类似时,大部分情况两者之间的效果似乎方向是一致的。 

            halcon的gen_gabor可视化结果                                      对应的滤波器输出

     LogGabor参数                            LogGabor可视化结果                            对应的滤波器结果

  上述结果的halcon代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
read_image (Image, 'fabrik')
get_image_size (Image, Width, Height)
gen_gabor(Filter,10,0.1,50,1.57,'n','dc_center',Width, Height)
fft_generic(Image,ImageFFT,'to_freq',-1,'none','dc_center','complex')
convol_gabor(ImageFFT,Filter,Gabor,Hilbert)
fft_generic(Gabor,GaborInv,'from_freq',1,'none','dc_center','byte')

  可以看出,两者的结果存在一定的相似性,从某个侧面说明我们的猜测具有一定的科学性。

  三、速度优化

  从上面的过程可以看到我们的LogGabor滤波器的生成有着较为复杂的计算公式,而且有多个函数调用,这些函数其实都是有着较为复杂的内部计算的,要进行优化,可以从多方面出发,第一个是用C语言处理吧,把一些公共的计算放到循环外部,把能优化掉的除法尽量改为乘法,还可以把那个exp的计算合并为一个,因为我们知道exp(a) * exp(b) = exp(a+b),这样就可以减少一次exp计算了。

  当然,我们还可以进行指令集优化,我们可以自定义_mm_atan2_ps, _mm_sincos_ps, _mm_exp_ps等等指令集函数(网络上可以找到的),他们可以接受成吨的输出。很爽,至少速度比C版本的提高3到4倍。

  我们在计算频域相乘时,也可以适当的考虑扩大图像,让图像的尺寸变为那些更有利于做FFT变换的数据,比如4、5、8的倍数等等,这样,可以有效地提高FFT的运算速度,并且对结果只会造成轻微的影响。

  关于这个算法目前就研究这么多吧,希望能造福有需要的人,也能造福自己。

  此更新算法位于我的SSE Demo的如下目录:   Detection(检测相关)---》Gabor Filter(Gabor滤波)。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[ISUX译]iOS 9人机界面指南(二):设计策略 - 腾讯ISUX
文章索引 2.1 设计原则(Design Principles) 2.1.1 美学完整性(Aesthetic Integrity) 2.1.2 一致性(Consistency) 2.1.3 直接操作(Direct Manipulation) 2.1.4 反馈(Feedback) 2.1.5 隐喻(Metaphors) 2.1.6 用户控制(User Control) 2.2 从概念到产品(From Concept to Product) 2.2.1 定义应用(Define Your App) 2.2.2 为
腾讯ISUX
2018/06/29
1.4K0
形式与功能 – 卡片式设计思考 - 腾讯ISUX
在互联网产品中,除了内容型外,一些功能型的产品信息内容也是相当巨大的,特别是管理控制系统,业务管理、功能操作、数据展示等。在信息量这么大的页面中除了重视内容质量外,形式功能的组织与呈现也是同等重要,对提高用户获取有效信息的效率有着非常大的帮助。 上面所说的形式功能的组织与呈现其实讲的是设计排版上的问题,当然对设计师排版功力也有相当的要求。这种排版优化的方法有很多种,我这里主要围绕卡片式设计的理论进行深入探讨,相信大家对卡片式设计已非常熟悉,虽然已流行了好多年,但是设计形式并不是随着使用年龄的增长而消失,芝加
腾讯ISUX
2018/06/29
1K0
Today Widget 抢占比桌面更重要的地盘 - 腾讯ISUX
Apple于去年发布的iOS8系统带来了许多有趣的新特性,其中的App Extensions让第三方产品与系统本体的互动变得更为直接。 “Today Widget”,”Get a quick update or perform a quick task in the Today view of Notification Center”(在通知中心的今日视图中快速获得更新或完成操作)——从此在许多场景下、用户毋须再前往桌面寻找icon进入app了,只需在屏幕上轻轻一Swipe(即使在未解锁状态下),就可以展开
腾讯ISUX
2018/06/29
6360
再见Metro,Windows 10通用应用设计趋势分析 - 腾讯ISUX
众所周知,当初微软在Windows 8上做了非常大胆的变革,除了开创性的Metro设计语言,传统桌面和平板两种模式的融合也是一大特色,可这两种操作模式在使用体验上的不一致也成为Windows 8饱受用户诟病的原因之一,但微软自始至终都朝着平台大融合的目标坚定前行着。 经过一路探索,微软终于通过在Windows 10系统的公布,展示了一个更加清晰明了的战略方向:构建一个面向全部Windows设备的核心操作系统。下面,本文就通过系统新特性和已公布的通用应用,来简单分析一下Windows 10通用应用的设计趋势。
腾讯ISUX
2018/06/29
1.2K0
见微知著,谈移动缺省页设计 - 腾讯ISUX
缺省页面,是出现在用户没有提交任何资料或者网络连接不通畅的情况下所展现的页面。通常设计师们习惯用丰富的数据内容把页面设计得美观实用,考虑的都是界面展现的“理想状态”,往往会忽视没有内容的“缺省状态”。
腾讯ISUX
2018/06/29
1.7K0
UI设计中的基本动效,值得收藏一波
1.滑动 信息列表会跟随着用户的交互手势而动,然后卡片到相应的位置上,保持整齐感,它属于指向型动画,物体的滑动取决于用户是用那种手势滑动的。它的作用就是通过指向型转场,有效帮助用户清理页面层级的排列情况。
用户5009027
2019/06/11
2.3K0
UI设计中的基本动效,值得收藏一波
用户教育产品化:设计产品化的微型实践 - 腾讯ISUX
在许多互联网公司中,设计工作往往被视为一项针对产品的服务,服务好产品是设计师职能的优先价值指标。观点固然不错却失于片面,因为服务体系与产品形态在设计内涵中是相互统一的。设计在实现解决产品问题、优化产品体验的目标同时,也能够通过建立产品语境获得更大的用户影响力与传播话语权。 因此,个人以为设计价值的归依不仅在于前者的解决,更有后者的创造。无论界面,品牌,内容皆然。 在企业产品(企业QQ,营销QQ)的用户教育项目中,我们尝试以形象内容设计为手段,通过产品化的尝试来实现设计效用的最大化。 1.从问题出发到解决方案
腾讯ISUX
2018/06/29
1.2K0
Apple Watch平台认知与产品设计 - 腾讯ISUX
时至今日,Apple Watch已然高调进入我们的视野,却仍未正式进入我们的世界,绝大多数人的信息来源仍限于Apple官方的介绍。大家有期许,有探索,也有失望。持负面态度者的普遍看法是,“这些事情在iPhone上都能做…手机屏幕那么大,看起来更爽用起来更舒服…令人心塞的续航能力仅支持5个小时的高强度使用…买它何用…”,而乐观者则普遍相信作为Apple设备生态圈的新生力量,Watch在技术上虽尚未成熟,却具有其他设备难以比拟的优势,并且会像前辈们那样欲扬先抑,在恰当的时间点爆发于消费市场。 失望者从很大程度上
腾讯ISUX
2018/06/29
8570
[ISUX转译]设计追波风 - 腾讯ISUX
前言 13年底,Intercom 的产品VP Paul Adams 在 Intercom 官博发表了 一篇博文 。文章讲述了网络上设计社区里普遍存在的一种现象,大意是“许多设计师在社区中分享的作品往往是为了炫技,而产品的逻辑通常都经不起推敲的,真正优秀的设计应该从更高的层面出发,而不只是做表面上的工作”。 文章发布后,在 Twitter 、HN 及博客评论下引起了反响。虽然部分内容在一些设计师眼里看起来比较有攻击性(也就是俗称“开喷”),甚至还带有些地图炮,但是文中关于“设计的四个层次”以及“when..I
腾讯ISUX
2018/06/29
6960
SaaS产品增效 | 通过腾讯会议布局优化,看如何简化用户任务
随着产品不断迭代,产品功能会逐渐丰富全面,但对于用户来说,是不是齐全的功能就等同于好的体验呢?本文将以“腾讯会议设置布局”交互优化为例,结合《设计心理学2》的相关理论,分享关于简化复杂任务的设计心得。 一、为何要“简化”任务 一款产品是不是功能越齐全多样就意味着越好的产品体验呢? 对于专家用户来说,当然是功能越全面越能满足自己的需求,但对于新手用户来说,全面的功能未必等同最佳的体验,过多操作挤在同一任务中,可能会让用户感到不知所措,难以上手。因此设计师应尽可能帮助用户简化任务,避免用户因为界面复杂而放弃任务
腾讯云设计中心
2023/01/11
8170
SaaS产品增效 | 通过腾讯会议布局优化,看如何简化用户任务
你的布局设定方法靠谱吗? - 腾讯ISUX
本文不适合采用天才设计(Genius Design)方法的人士。 有一种“奇怪的”现象会经常的看到“很多设计师没有办法清楚的跟其他人解释他们是如何设计的,越细致的地方可能越是如此。比如,这个菜单的宽度为什么是200px?250px或者190px是否可以?图片的尺寸为什么是278px*196px?如何确定网页的宽度?“ 软件界面的设计师除了视觉本身以外,对于设计是否可以实现、大概以何种方式实现、规范可否被理解并且复制执行、设计实现的性价比与时间比等纬度都应有相当高度的认识。就像建筑设计师一样,他们一定很了解建
腾讯ISUX
2018/06/29
7160
不能不说的设计秘密——4个步骤提升交互思维
良好的用户体验包含很多内容:服务、产品、参与者的感受等等,显然产品功能的强大、界面的美观并不能完全概括体验。体验还包含在产品与用户之间的互动、产品与场景的交互、产品对用户的情绪上的影响等等的细枝末节中。 交互设计是设计人与产品接触的动态时间轴上的每一次接触,从一开始的靠近、到产生共鸣、赞美,在每一个接触行为的背后都有需要关注的用户情绪、需要理解的用户认知。卡耐基 · 梅隆大学设计学院的John Zimmerman等提出了一个设计过程发现和汲取知识的流程框架:define(定义)、discover(发现)、s
腾讯大讲堂
2018/02/13
8590
不能不说的设计秘密——4个步骤提升交互思维
豆瓣网可用性测试报告
  豆瓣网简介:豆瓣(douban)是一个社区网站。网站由杨勃(网名“阿北”) 创立于2005年3月6日。该网站以书影音起家,提供关于书籍、电影、音乐等作品的信息,无论描述还是评论都由用户提供(User-generated content,UGC),是Web 2.0网站中具有特色的一个网站。网站还提供书影音推荐、线下同城活动、小组话题交流等多种服务功能,它更像一个集品味系统(读书、电影、音乐)、表达系统(我读、我看、我听)和交流系统(同城、小组、友邻)于一体的创新网络服务,一直致力于帮助都市人群发现生活中有用的事物。
顾翔
2019/12/12
1.2K0
豆瓣网可用性测试报告
WebSocket实现多屏互动的分析及方案 - 腾讯ISUX
多屏互动事实上是一个比较宽泛的概念,通俗来讲就是用户在不同的终端上通过有线、无线的连接方式进行通信,可进行多媒体(音频,视频,图片)内容的传输,解析,展示,控制等一系列操作。而随着WebSocket协议的诞生,不同端之间的网页互连也变得流行起来,这种基于WebSocket协议实现多屏互动在运营活动上的使用也使得运营页面的形式也变得更加多样和有趣。 本文不会去探讨WebSocket协议的详情,想了解的可以点击https://tools.ietf.org/html/rfc6455查看协议文档。 在了解Webso
腾讯ISUX
2018/06/29
1.6K0
告别黄页时代,让设计鲜活起来
每年的双11都格外疯狂,随着技术带动内容的丰富化,刚过去的双11气氛在大众购买力的飙升下又刷新高,让人一夜之间感受到运营力量的震撼来袭。在血脉喷张各种抢购倒持购物车时的你,可否留意过无形之中的商城装扮。众多电商app从整个界面翻新到内部的运营活动抽奖机制,堪比一座物欲相抗衡的虚拟不夜城。 这些多样化而不失秩序的运营设计,背后支撑着有序的设计原则。如今形式内容纷呈的移动互联列队中,充斥着综合垂直电商、团购、旅游、生鲜等2C市场应用的身影,以丰富化运营方式攻占联结产业链,而黄页类生活资讯类应用相对显得务实,部分
腾讯ISUX
2018/06/29
1.1K0
QQ音乐V5 : 星设定 - 腾讯ISUX
悄然间,QQ音乐已陪伴大家十个年头,从PC互联网时代走到了移动互联网时代QQ音乐一直探索和坚持着简约时尚的设计语言。几经迭代,以内容为导向的页面排版略显保守,新版的视觉在品牌元素加入,突出音乐元素的表达,尝试从新的角度诠释简约时尚的设计语言。 如今的移动应用软件设计已经不再是简单跟随手机系统设计,有个性有品牌感的产品会更加受到用户喜欢。我们通过用户调研,也了解到用户对个性化界面的诉求,比如酷炫的皮肤,大图模式和动画的设计。产品和设计希望新版视觉在个性化和品牌感上有所突破,一方面满足用户诉求,另一方面也能全面
腾讯ISUX
2018/06/29
9000
玩转HTML5移动页面(优化篇)- 腾讯ISUX
承接上文《玩转HTML5移动页面(动效篇)》,上次说的是让页面动起来的一些小技巧。 而页面动起来的根基是功能可用的页面,因此有必要分享一些优化细节的技巧和方向,熟悉掌握一些方法论还是会对页面开发大大提高效率的,并且也能防止疏忽缺漏。 ====前方高能==== (1) 动画雪碧图 涉及的动画十分多,用的元素也十分多,请务必使用雪碧图 (Sprite)! 网上的工具有一些可以帮助你生成雪碧图的工具,例如CssGaga,GoPng等等,自动化构建工具Grunt和Gulp也提供了相应插件。 特别地,如果单张
腾讯ISUX
2018/06/29
1.1K0
设计探索|重新认识UX文案
讲到UX文案,大家可能并不陌生:一个按钮、一个弹窗的文案填充,我们几乎每天都要与他接触。但即便如此,大家对他的态度通常是得过且过的:“文案嘛,有了就行,看得懂不出错就好,没什么值得注意的”。 确实,作为设计师,我们关注交互流程、视觉呈现,但UX文案似乎从来不是我们的首要考虑;在很多时候,文案与我们的设计流程是分裂的:要不就是设计完成后再填入,要不甚至直接让产品经理来提供文案素材;文案撰写,好像从来没有被我们真正重视过。 但UX文案真的只是一个无足轻重的辅助位吗? 一、  UX文案的重要性 首先,先抛结论,U
腾讯ISUX
2023/01/05
8190
设计探索|重新认识UX文案
盘一盘国内3款Linux 控制面板
在当今的互联网技术领域,Linux 操作系统凭借其开源、稳定、安全等诸多优势被广泛应用于服务器搭建等场景。而与之配套的 Linux 控制面板则成为了众多运维人员和开发者便捷管理服务器、部署应用的重要工具。国内市场上存在着多款各具特色的 Linux 控制面板,本文将选取宝塔、cPanel 以及 Websoft9 这三款具有代表性的产品进行深入对比分析,旨在呈现它们各自的特点,尤其突出 Websoft9 以部署和维护开源应用为中心的独特性,帮助读者更好地了解并根据自身需求做出合适的选择。
用户11372075
2024/11/21
3310
盘一盘国内3款Linux 控制面板
以任务为核心的 BTSD 设计模型
提起 B 端设计,我们可能下意识的会想起后台设计,大部分情况是以 PC 端为主的界面设计。更深一步去想,B 端设计的需求来源是复杂业务,设计师的主要工作是为了满足这些需求给出合理方案。在大量的需求和逻辑中,设计师的方案往往顾此失彼,使得设计不能同时满足用户体验和业务需求。
我只是会一点编程
2022/04/01
6642
相关推荐
[ISUX译]iOS 9人机界面指南(二):设计策略 - 腾讯ISUX
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验