博主对其开展了归纳的bug改正以及质量优化,  该算法进行不难的修改可作图像增强之用

前段时间在网上看到2个十分的快均值模糊算法,质量很不利。

快快均值模糊算法,均值模糊算法

前段时间在网上看看二个快速均值模糊算法,质量很科学。

源博客:

http://www.lellansin.com/super-fast-blur-%E6%A8%A1%E7%B3%8A%E7%AE%97%E6%B3%95.html

博主对其实行了简易的bug立异以及质量优化。

在博主机子上应用该算法对一张5000×3000的图样展开模糊处理,仅需500-600微秒,速度相当慢。

图片 1

代码如下:

/*

* Super Fast Blur v1.1+

* Original author: Mario Klingemann (C++ version)
* Original address: http://incubator.quasimondo.com/processing/superfastblur.pde

* C version updated by Lellansin (http://www.lellansin.com)
* C version bugfix and performance optimization by tntmonks (http://tntmonks.cnblogs.com)
*/

void superFastBlur(unsigned char *pix, unsigned int w, unsigned int h, unsigned int comp, int radius)
{
 unsigned int div;
 unsigned int wm, hm, wh;
 unsigned int *vMIN, *vMAX;
 unsigned char *r, *g, *b, *dv;
 unsigned int rsum, gsum, bsum;
 unsigned int p, p1, p2, yi, yw;

 int x, y, i, yp;
 if (radius < 1)
  return;
 wm = w - 1;
 hm = h - 1;
 wh = w * h;
 div = radius + radius + 1;
 vMIN = (unsigned int *)malloc(sizeof(unsigned int) * max(w, h));
 vMAX = (unsigned int *)malloc(sizeof(unsigned int) * max(w, h));
 r = (unsigned char *)malloc(sizeof(unsigned char) * wh);
 g = (unsigned char *)malloc(sizeof(unsigned char) * wh);
 b = (unsigned char *)malloc(sizeof(unsigned char) * wh);
 dv = (unsigned char *)malloc(sizeof(unsigned char) * 256 * div);


 for (i = 0; i < 256 * div; i++)

  dv[i] = (i / div);


 yw = yi = 0;
 for (y = 0; y < h; y++)
 {
  rsum = gsum = bsum = 0;
  for (i = -radius; i <= radius; i++)
  {
   p = (yi + min(wm, max(i, 0))) * comp;
   bsum += pix[p];
   gsum += pix[p + 1];
   rsum += pix[p + 2];
  }

  for (x = 0; x < w; x++)
  {
   r[yi] = dv[rsum];
   g[yi] = dv[gsum];
   b[yi] = dv[bsum];

   if (y == 0)
   {
    vMIN[x] = min(x + radius + 1, wm);
    vMAX[x] = max(x - radius, 0);
   }
   p1 = (yw + vMIN[x]) * comp;
   p2 = (yw + vMAX[x]) * comp;
   bsum += pix[p1] - pix[p2];
   gsum += pix[p1 + 1] - pix[p2 + 1];
   rsum += pix[p1 + 2] - pix[p2 + 2];
   yi++;
  }
  yw += w;
 }


 for (x = 0; x < w; x++)
 {
  rsum = gsum = bsum = 0;
  yp = -radius * w;
  for (i = -radius; i <= radius; i++)
  {
   yi = max(0, yp) + x;
   rsum += r[yi];
   gsum += g[yi];
   bsum += b[yi];
   yp += w;
  }

  yi = x;
  for (y = 0; y < h; y++)
  { 
   pix[yi * comp] = (dv[bsum]);
   pix[yi * comp + 1] = (dv[gsum]);
   pix[yi * comp + 2] = (dv[rsum]);

   if (x == 0)
   {
    vMIN[y] = min(y + radius + 1, hm) * w;
    vMAX[y] = max(y - radius, 0) * w;
   }
   p1 = x + vMIN[y];
   p2 = x + vMAX[y];

   rsum += r[p1] - r[p2];
   gsum += g[p1] - g[p2];
   bsum += b[p1] - b[p2];
   yi += w;
  }
 } 

 free(r); 
 free(g); 
 free(b); 
 free(vMIN); 
 free(vMAX); 
 free(dv);
}

  该算法进行简要的改动可作图像增强之用。

该算法还是能进一步优化,那些职务就付给各位看官咯。

http://www.bkjia.com/cjjc/1063035.htmlwww.bkjia.comtruehttp://www.bkjia.com/cjjc/1063035.htmlTechArticle快速均值模糊算法,均值模糊算法
前段时间在网上看到三个连忙均值模糊算法,品质很科学。 源博客:
http://www.lellansin.com/super-fast-blur-%

强烈,

源博客:

图像方面包车型客车3A算法有:

http://www.lellansin.com/super-fast-blur-%E6%A8%A1%E7%B3%8A%E7%AE%97%E6%B3%95.html

AF自动对焦(Automatic Focus)
活动对焦即调节录制头焦距自动获取清晰的图像的长河

博主对其进展了简要的bug校勘以及质量优化。

AE自动揭露(Automatic Exposure)
自动暴露的是为着使感光器件得到优异的暴光量

在博主机子上使用该算法对一张陆仟x两千的图纸展开模糊处理,仅需500-600阿秒,速度一点也非常的慢。

AW自动白平衡(Automatic 惠特e Balance)
白平衡的真面目是使黑古铜色物体在其他光源下都来得青古铜色

图片 2

前方的作品也有提起过,在刚开始做图像算法的时候,小编是先攻克的全自动白平衡算法。

代码如下:

新生打下自动暴光的时候,傻啊吧唧的,踩了无独有偶坑。

/*

* Super Fast Blur v1.1+

* Original author: Mario Klingemann (C++ version)
* Original address: http://incubator.quasimondo.com/processing/superfastblur.pde

* C version updated by Lellansin (http://www.lellansin.com)
* C version bugfix and performance optimization by tntmonks (http://tntmonks.cnblogs.com)
*/

void superFastBlur(unsigned char *pix, unsigned int w, unsigned int h, unsigned int comp, int radius)
{
    unsigned int div;
    unsigned int wm, hm, wh;
    unsigned int *vMIN, *vMAX;
    unsigned char *r, *g, *b, *dv;
    unsigned int rsum, gsum, bsum;
    unsigned int p, p1, p2, yi, yw;

    int x, y, i, yp;
    if (radius < 1)
        return;
    wm = w - 1;
    hm = h - 1;
    wh = w * h;
    div = radius + radius + 1;
    vMIN = (unsigned int *)malloc(sizeof(unsigned int) * max(w, h));
    vMAX = (unsigned int *)malloc(sizeof(unsigned int) * max(w, h));
    r = (unsigned char *)malloc(sizeof(unsigned char) * wh);
    g = (unsigned char *)malloc(sizeof(unsigned char) * wh);
    b = (unsigned char *)malloc(sizeof(unsigned char) * wh);
    dv = (unsigned char *)malloc(sizeof(unsigned char) * 256 * div);


    for (i = 0; i < 256 * div; i++)

        dv[i] = (i / div);


    yw = yi = 0;
    for (y = 0; y < h; y++)
    {
        rsum = gsum = bsum = 0;
        for (i = -radius; i <= radius; i++)
        {
            p = (yi + min(wm, max(i, 0))) * comp;
            bsum += pix[p];
            gsum += pix[p + 1];
            rsum += pix[p + 2];
        }

        for (x = 0; x < w; x++)
        {
            r[yi] = dv[rsum];
            g[yi] = dv[gsum];
            b[yi] = dv[bsum];

            if (y == 0)
            {
                vMIN[x] = min(x + radius + 1, wm);
                vMAX[x] = max(x - radius, 0);
            }
            p1 = (yw + vMIN[x]) * comp;
            p2 = (yw + vMAX[x]) * comp;
            bsum += pix[p1] - pix[p2];
            gsum += pix[p1 + 1] - pix[p2 + 1];
            rsum += pix[p1 + 2] - pix[p2 + 2];
            yi++;
        }
        yw += w;
    }


    for (x = 0; x < w; x++)
    {
        rsum = gsum = bsum = 0;
        yp = -radius * w;
        for (i = -radius; i <= radius; i++)
        {
            yi = max(0, yp) + x;
            rsum += r[yi];
            gsum += g[yi];
            bsum += b[yi];
            yp += w;
        }

        yi = x;
        for (y = 0; y < h; y++)
        { 
            pix[yi * comp] = (dv[bsum]);
            pix[yi * comp + 1] = (dv[gsum]);
            pix[yi * comp + 2] = (dv[rsum]);

            if (x == 0)
            {
                vMIN[y] = min(y + radius + 1, hm) * w;
                vMAX[y] = max(y - radius, 0) * w;
            }
            p1 = x + vMIN[y];
            p2 = x + vMAX[y];

            rsum += r[p1] - r[p2];
            gsum += g[p1] - g[p2];
            bsum += b[p1] - b[p2];
            yi += w;
        }
    } 

    free(r); 
    free(g); 
    free(b); 
    free(vMIN); 
    free(vMAX); 
    free(dv);
}

作者深信肯定不止自个儿叁个,一起始的时候抱着对图像均衡化,

  该算法举行简易的改动可作图像增强之用。

软磨硬泡,想要做出兼顾自动暴光和机动白平衡的算法。

该算法还是能进一步优化,这些职务就付给各位看官咯。

惋惜,图像均衡化去做白平衡恐怕电动暴光,那条路是错的。

适度从紧意义上来说,图像均衡化是拉伸曲线,那种做法有个弊端。

它并未有怀恋到图像的空间新闻,也便是局地音讯。

本来若是是拍卖音频之类的算法,肯定要思索时间新闻,因为数量是时序性为主的。

而图像,明显是空间音信为主的。

之所以从理论上的话,用拉伸曲线那种不有所空间音信的操作,来做空间新闻处理的事情,是不正确的。

本人记得那博客刚起首写的时候,好多网上朋友问笔者,为何你要写那么多图像模糊算法,

图像模糊算法好像很鸡肋啊,没什么用的吗。

那就大错特错了,因为模糊算法是图像算法中,典型的含有空间音讯的全局算法。

也正是说,如若要玩好图像算法,玩好模糊算法正是标配。

本次分享的算法为《Local Color Correction using Non-Linear
Masking》,是ImageShop博主,

彭兄发出来的,安利一下她的博客https://www.cnblogs.com/imageshop。

以此小说里的算法相比简单,

驷不比舌是经过图像模糊获取局域权重音信,然后映射回图片上。

matlab代码如下:

% Read the imageA=imread('input.jpg');% Seperate the ChannelsR=A(:,:,1);G=A(:,:,2);B=A(:,:,3);% Calculate Intensity ComponentI=/3;% Invert the imageI_inverted=255-I;% Apply Average Filter to obtain the Mask Imageh_average=fspecial('average',15);M=imfilter(I_inverted,h_average);% Color Correction for R channelR_new=zeros;[c_y, c_x,~] = size;for j = 1:c_x        for i = 1:c_y            p=double;            q=double;            R_new=int8(255*((p/255)^(2^((128-q)/128))));        endend% Color Correction for G channelG_new=zeros;[c_y, c_x,~] = size;for j = 1:c_x        for i = 1:c_y            p=double;            q=double;            G_new=int8(255*((p/255)^(2^((128-q)/128))));        endend% Color Correction for B channelB_new=zeros;[c_y, c_x,~] = size;for j = 1:c_x        for i = 1:c_y            p=double;            q=double;            B_new=int8(255*((p/255)^(2^((128-q)/128))));        endend% Output ImageO=zeros;O(:,:,1)=R_new;O(:,:,2)=G_new;O(:,:,3)=B_new;% Convert the double output image to uint8O=uint8;% Plot the imagessubplot(1,3,1), imshow, title('Original Image');subplot(1,3,2), imshow, title('Mask');subplot(1,3,3), imshow, title('Output Image');

算法步骤很清楚,就不实行了。

有趣味的同班,品读下随想呢。

诗歌链接直达

那么些算法其实只是简简单单利用局地消息进行揭露调节,

不过并不可能很好的适配很多图形情景。

亟需展开三次改造,

比如: 白平衡,纹理处理越发自然诸如此类,之后就能更美美哒。

师傅领进门,修行在个人。

一字不苟的思绪和办法就不开始展览①一细说了,

有趣味的校友,能够设想进一步核对。

效能图如下:

图片 3

图片 4

首要的算法函数实现如下:

void LocalColorCorrection(unsigned char *Input, unsigned char *Output, int Width, int Height, int Channels) {    unsigned char *Mask = (unsigned char *) malloc(Width * Height * sizeof(unsigned char));    if (Mask == NULL)        return;    unsigned char LocalLut[256 * 256];    for (int mask = 0; mask < 256; ++mask) {        unsigned char *pLocalLut = LocalLut + (mask << 8);        for (int pix = 0; pix < 256; ++pix) {            pLocalLut[pix] = ClampToByte(255.0f * powf(pix / 255.0f, powf(2.0f, (128.0f - mask) / 128.0f)));        }    }    InvertGrayscale(Input, Output, Width, Height, Channels);    int Radius = (MAX(Width, Height) / 512) + 1;    BoxBlurGrayscale(Output, Mask, Width, Height, Radius);    for (int Y = 0; Y < Height; Y++) {        unsigned char *pOutput = Output + (Y * Width * Channels);        unsigned char *pInput = Input + (Y * Width * Channels);        unsigned char *pMask = Mask + (Y * Width);        for (int X = 0; X < Width; X++) {            unsigned char *pLocalLut = LocalLut + (pMask[X] << 8);            for (int C = 0; C < Channels; C++) {                pOutput[C] = pLocalLut[pInput[C]];            }            pOutput += Channels;            pInput += Channels;        }    }    free;}

做了部分算法质量上的优化,720P,拾80P下实时没半点难题。

至于进一步优化质量和成效,就留待下回分解,

理所当然有未有下回,得看心绪。

附完整C代码:

/***implmentation of Local Color Correction using Non-Linear Masking published by Nathan Moroney Hewlett-Packard Laboratories, Palo Alto, California. **/#include "browse.h"#define USE_SHELL_OPEN#define STB_IMAGE_STATIC#define STB_IMAGE_IMPLEMENTATION#include "stb_image.h"/* ref:https://github.com/nothings/stb/blob/master/stb_image.h */#define TJE_IMPLEMENTATION#include "tiny_jpeg.h"/* ref:https://github.com/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h */#include <math.h>#include <stdbool.h>#include <stdio.h>#include "timing.h"#include <stdint.h>#include <assert.h>#ifndef _MAX_DRIVE#define _MAX_DRIVE 3#endif#ifndef _MAX_FNAME#define _MAX_FNAME 256#endif#ifndef _MAX_EXT#define _MAX_EXT 256#endif#ifndef _MAX_DIR#define _MAX_DIR 256#endif#ifndef MIN#define MIN     >  : #endif#ifndef MAX#define MAX  >  : #endifchar saveFile[1024];unsigned char *loadImage(const char *filename, int *Width, int *Height, int *Channels) {    return (stbi_load(filename, Width, Height, Channels, 0));}void saveImage(const char *filename, int Width, int Height, int Channels, unsigned char *Output) {    memcpy(saveFile + strlen, filename, strlen);    *(saveFile + strlen + 1) = 0;    if (!tje_encode_to_file(saveFile, Width, Height, Channels, true, Output)) {        fprintf(stderr, "save JPEG fail.\n");        return;    }#ifdef USE_SHELL_OPEN    browse;#endif}void splitpath(const char *path, char *drv, char *dir, char *name, char *ext) {    const char *end;    const char *p;    const char *s;    if (path[0] && path[1] == ':') {        if  {            *drv++ = *path++;            *drv++ = *path++;            *drv = '\0';        }    } else if         *drv = '\0';    for (end = path; *end && *end != ':';)        end++;    for (p = end; p > path && *--p != '\\' && *p != '/';)        if (*p == '.') {            end = p;            break;        }    if         for (s = end; (*ext = *s++);)            ext++;    for (p = end; p > path;)        if (*--p == '\\' || *p == '/') {            p++;            break;        }    if  {        for (s = p; s < end;)            *name++ = *s++;        *name = '\0';    }    if  {        for (s = path; s < p;)            *dir++ = *s++;        *dir = '\0';    }}void getCurrentFilePath(const char *filePath, char *saveFile) {    char drive[_MAX_DRIVE];    char dir[_MAX_DIR];    char fname[_MAX_FNAME];    char ext[_MAX_EXT];    splitpath(filePath, drive, dir, fname, ext);    size_t n = strlen;    memcpy(saveFile, filePath, n);    char *cur_saveFile = saveFile + (n - strlen;    cur_saveFile[0] = '_';    cur_saveFile[1] = 0;}int GetMirrorPos(int Length, int Pos) {    if (Pos < 0)        return -Pos;    else if (Pos >= Length)        return Length + Length - Pos - 2;    else        return Pos;}unsigned char ClampToByte(int Value) {    if (Value < 0)        return 0;    else if (Value > 255)        return 255;    else        return (unsigned char) Value;}void FillLeftAndRight_Mirror(int *Array, int Length, int Radius) {    for (int X = 0; X < Radius; X++) {        Array[X] = Array[Radius + Radius - X];        Array[Radius + Length + X] = Array[Radius + Length - X - 2];    }}int SumOfArray(const int *Array, int Length) {    int Sum = 0;    for (int X = 0; X < Length; X++) {        Sum += Array[X];    }    return Sum;}void BoxBlurGrayscale(unsigned char *input, unsigned char *output, int Width, int Height, int Radius) {    if ((input == NULL) || (output == NULL)) return;    if ((Width <= 0) || (Height <= 0) || (Radius <= 0)) return;    if (Radius < 1) return;    Radius = MIN(MIN(Radius, Width - 1), Height - 1);    int SampleAmount = (2 * Radius + 1) * (2 * Radius + 1);    float Inv = 1.0f / SampleAmount;    int *ColValue = (int *) malloc((Width + Radius + Radius) * sizeof(int));    int *ColOffset = (int *) malloc((Height + Radius + Radius) * sizeof(int));    if ((ColValue == NULL) || (ColOffset == NULL)) {        if (ColValue != NULL) free;        if (ColOffset != NULL) free(ColOffset);        return;    }    for (int Y = 0; Y < Height + Radius + Radius; Y++)        ColOffset[Y] = GetMirrorPos(Height, Y - Radius);    {        for (int Y = 0; Y < Height; Y++) {            unsigned char *scanLineOut = output + Y * Width;            if (Y == 0) {                memset(ColValue + Radius, 0, Width * sizeof(int));                for (int Z = -Radius; Z <= Radius; Z++) {                    unsigned char *scanLineIn = input + ColOffset[Z + Radius] * Width;                    for (int X = 0; X < Width; X++) {                        ColValue[X + Radius] += scanLineIn[X];                    }                }            } else {                unsigned char *RowMoveOut = input + ColOffset[Y - 1] * Width;                unsigned char *RowMoveIn = input + ColOffset[Y + Radius + Radius] * Width;                for (int X = 0; X < Width; X++) {                    ColValue[X + Radius] -=                            RowMoveOut[X] - RowMoveIn[X];                }            }            FillLeftAndRight_Mirror(ColValue, Width, Radius);            int LastSum = SumOfArray(ColValue, Radius * 2 + 1);            scanLineOut[0] = ClampToByte((int) (LastSum * Inv));            for (int X = 0 + 1; X < Width; X++) {                int NewSum = LastSum - ColValue[X - 1] + ColValue[X + Radius + Radius];                scanLineOut[X] = ClampToByte((int) (NewSum * Inv));                LastSum = NewSum;            }        }    }    free;    free(ColOffset);}void InvertGrayscale(unsigned char *Input, unsigned char *Output, int Width, int Height, int Channels) {    if (Channels == 1) {        for (unsigned int Y = 0; Y < Height; Y++) {            unsigned char *pOutput = Output + (Y * Width);            unsigned char *pInput = Input + (Y * Width);            for (unsigned int X = 0; X < Width; X++) {                pOutput[X] = (unsigned char) (255 - pInput[X]);            }        }    } else {        for (unsigned int Y = 0; Y < Height; Y++) {            unsigned char *pOutput = Output + (Y * Width);            unsigned char *pInput = Input + (Y * Width * Channels);            for (unsigned int X = 0; X < Width; X++) {                pOutput[X] = (unsigned char) (255 - ClampToByte(                        (21842 * pInput[0] + 21842 * pInput[1] + 21842 * pInput[2]) >> 16));                pInput += Channels;            }        }    }}void LocalColorCorrection(unsigned char *Input, unsigned char *Output, int Width, int Height, int Channels) {    unsigned char *Mask = (unsigned char *) malloc(Width * Height * sizeof(unsigned char));    if (Mask == NULL)        return;    unsigned char LocalLut[256 * 256];    for (int mask = 0; mask < 256; ++mask) {        unsigned char *pLocalLut = LocalLut + (mask << 8);        for (int pix = 0; pix < 256; ++pix) {            pLocalLut[pix] = ClampToByte(255.0f * powf(pix / 255.0f, powf(2.0f, (128.0f - mask) / 128.0f)));        }    }    InvertGrayscale(Input, Output, Width, Height, Channels);    int Radius = (MAX(Width, Height) / 512) + 1;    BoxBlurGrayscale(Output, Mask, Width, Height, Radius);    for (int Y = 0; Y < Height; Y++) {        unsigned char *pOutput = Output + (Y * Width * Channels);        unsigned char *pInput = Input + (Y * Width * Channels);        unsigned char *pMask = Mask + (Y * Width);        for (int X = 0; X < Width; X++) {            unsigned char *pLocalLut = LocalLut + (pMask[X] << 8);            for (int C = 0; C < Channels; C++) {                pOutput[C] = pLocalLut[pInput[C]];            }            pOutput += Channels;            pInput += Channels;        }    }    free;}int main(int argc, char **argv) {    printf("Local Color Correction demo\n ");    printf("blog:http://cpuimage.cnblogs.com/ \n ");    if (argc < 2) {        printf("usage: %s   image \n ", argv[0]);        printf("eg: %s   d:\\image.jpg \n ", argv[0]);        return (0);    }    char *szfile = argv[1];    getCurrentFilePath(szfile, saveFile);    int Width = 0;    int Height = 0;    int Channels = 0;    unsigned char *inputImage = NULL;    double startTime = now();    inputImage = loadImage(szfile, &Width, &Height, &Channels);    double nLoadTime = calcElapsed(startTime, now;    printf("load time: %d ms.\n ", (int) (nLoadTime * 1000));    if ((Channels != 0) && (Width != 0) && (Height != 0)) {        unsigned char *outputImg = (unsigned char *) stbi__malloc(Width * Channels * Height * sizeof(unsigned char));        if (inputImage) {            memcpy(outputImg, inputImage,  (Width * Channels * Height));        } else {            printf("load: %s fail!\n ", szfile);        }        startTime = now();        LocalColorCorrection(inputImage, outputImg, Width, Height, Channels);        double nProcessTime = calcElapsed(startTime, now;        printf("process time: %d ms.\n ", (int) (nProcessTime * 1000));        startTime = now();        saveImage("done.jpg", Width, Height, Channels, outputImg);        double nSaveTime = calcElapsed(startTime, now;        printf("save time: %d ms.\n ", (int) (nSaveTime * 1000));        if (outputImg) {            stbi_image_free(outputImg);        }        if (inputImage) {            stbi_image_free(inputImage);        }    } else {        printf("load: %s fail!\n", szfile);    }    getchar();    printf("press any key to exit. \n");    return (EXIT_SUCCESS);}

品类地址:https://github.com/cpuimage/LocalColorCorrection

再来四个效果前后相比较:

图片 5图片 6

上述,权当引玉之砖。

若有任何有关难点要么需求也足以邮件联系笔者探究。

邮箱地址是:
gaozhihan@vip.qq.com

相关文章