UIImage / CGImage的标准偏差

时间:2023-02-01 14:57:43

I need to calculate the standard deviation on an image I have inside a UIImage object. I know already how to access all pixels of an image, one at a time, so somehow I can do it. I'm wondering if there is somewhere in the framework a function to perform this in a better and more efficient way... I can't find it so maybe it doensn't exist. Do anyone know how to do this? bye

我需要计算UIImage对象内部图像的标准偏差。我已经知道如何一次一个地访问图像的所有像素,所以不知怎的,我可以做到。我想知道框架中是否存在一个以更好,更有效的方式执行此操作的功能......我找不到它所以也许它不存在。有谁知道怎么做?再见

2 个解决方案

#1


4  

To further expand on my comment above. I would definitely look into using the Accelerate framework, especially depending on the size of your image. If you image is a few hundred pixels by a few hundred. You will have a ton of data to process and Accelerate along with vDSP will make all of that math a lot faster since it processes everything on the GPU. I will look into this a little more, and possibly put some code in a few minutes.

进一步扩展我上面的评论。我肯定会考虑使用Accelerate框架,特别是取决于图像的大小。如果你的图像是几百像素几百。您将需要处理大量数据,并且与vDSP一起加速将使所有数学运算更快,因为它处理GPU上的所有内容。我会再研究一下这个问题,并且可能会在几分钟内完成一些代码。

UPDATE

I will post some code to do standard deviation in a single dimension using vDSP, but this could definitely be extended to 2-D

我将发布一些代码,使用vDSP在单个维度上进行标准偏差,但这绝对可以扩展到2-D

 float *imageR =  [0.1,0.2,0.3,0.4,...]; // vector of values
 int numValues = 100; // number of values in imageR
 float mean = 0; // place holder for mean
 vDSP_meanv(imageR,1,&mean,numValues); // find the mean of the vector
 mean = -1*mean // Invert mean so when we add it is actually subtraction
 float *subMeanVec  = (float*)calloc(numValues,sizeof(float)); // placeholder vector
 vDSP_vsadd(imageR,1,&mean,subMeanVec,1,numValues) // subtract mean from vector
 free(imageR); // free memory 
 float *squared = (float*)calloc(numValues,sizeof(float)); // placeholder for squared vector
 vDSP_vsq(subMeanVec,1,squared,1,numValues); // Square vector element by element
 free(subMeanVec); // free some memory
 float sum = 0; // place holder for sum
 vDSP_sve(squared,1,&sum,numValues); sum entire vector
 free(squared); // free squared vector
 float stdDev = sqrt(sum/numValues); // calculated std deviation

#2


2  

Please explain your query so that can come up with specific reply.

请解释您的查询,以便能够提出具体的答复。

If I am getting you right then you want to calculate standard deviation of RGB of pixel or HSV of color, you can frame your own method of standard deviation for circular quantities in case of HSV and RGB.

如果我找到了你想要计算像素的RGB或颜色的HSV的标准偏差,你可以在HSV和RGB的情况下为循环量构建自己的标准偏差方法。

We can do this by wrapping the values. For example: Average of [358, 2] degrees is (358+2)/2=180 degrees. But this is not correct because its average or mean should be 0 degrees. So we wrap 358 into -2. Now the answer is 0. So you have to apply wrapping and then you can calculate standard deviation from above link.

我们可以通过包装值来实现。例如:[358,2]度的平均值是(358 + 2)/ 2 = 180度。但这不正确,因为它的平均值或平均值应为0度。所以我们将358包装成-2。现在答案是0.所以你必须应用包装,然后你可以从上面的链接计算标准偏差。

UPDATE: Convert RGB to HSV

更新:将RGB转换为HSV

    // r,g,b values are from 0 to 1 // h = [0,360], s = [0,1], v = [0,1]
//  if s == 0, then h = -1 (undefined)

void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v )

{
 float min, max, delta;   
    min = MIN( r, MIN(g, b ));   
    max = MAX( r, MAX(g, b ));   
    *v = max;  
    delta = max - min;   
    if( max != 0 )  
        *s = delta / max;  
    else {   
        // r = g = b = 0   
        *s = 0;   
        *h = -1;   
        return; 
    }
    if( r == max )
        *h = ( g - b ) / delta; 
    else if( g == max )
        *h=2+(b-r)/delta;
    else 
        *h=4+(r-g)/delta; 
    *h *= 60;
    if( *h < 0 ) 
        *h += 360;
}

and then calculate standard deviation for hue value by this:

然后通过以下方法计算色调值的标准偏差:

double calcStddev(ArrayList<Double> angles){
  double sin = 0;
  double cos = 0;
  for(int i = 0; i < angles.size(); i++){
       sin += Math.sin(angles.get(i) * (Math.PI/180.0));
       cos += Math.cos(angles.get(i) * (Math.PI/180.0)); 
  }
  sin /= angles.size();
  cos /= angles.size();

  double stddev = Math.sqrt(-Math.log(sin*sin+cos*cos));

  return stddev;

}

#1


4  

To further expand on my comment above. I would definitely look into using the Accelerate framework, especially depending on the size of your image. If you image is a few hundred pixels by a few hundred. You will have a ton of data to process and Accelerate along with vDSP will make all of that math a lot faster since it processes everything on the GPU. I will look into this a little more, and possibly put some code in a few minutes.

进一步扩展我上面的评论。我肯定会考虑使用Accelerate框架,特别是取决于图像的大小。如果你的图像是几百像素几百。您将需要处理大量数据,并且与vDSP一起加速将使所有数学运算更快,因为它处理GPU上的所有内容。我会再研究一下这个问题,并且可能会在几分钟内完成一些代码。

UPDATE

I will post some code to do standard deviation in a single dimension using vDSP, but this could definitely be extended to 2-D

我将发布一些代码,使用vDSP在单个维度上进行标准偏差,但这绝对可以扩展到2-D

 float *imageR =  [0.1,0.2,0.3,0.4,...]; // vector of values
 int numValues = 100; // number of values in imageR
 float mean = 0; // place holder for mean
 vDSP_meanv(imageR,1,&mean,numValues); // find the mean of the vector
 mean = -1*mean // Invert mean so when we add it is actually subtraction
 float *subMeanVec  = (float*)calloc(numValues,sizeof(float)); // placeholder vector
 vDSP_vsadd(imageR,1,&mean,subMeanVec,1,numValues) // subtract mean from vector
 free(imageR); // free memory 
 float *squared = (float*)calloc(numValues,sizeof(float)); // placeholder for squared vector
 vDSP_vsq(subMeanVec,1,squared,1,numValues); // Square vector element by element
 free(subMeanVec); // free some memory
 float sum = 0; // place holder for sum
 vDSP_sve(squared,1,&sum,numValues); sum entire vector
 free(squared); // free squared vector
 float stdDev = sqrt(sum/numValues); // calculated std deviation

#2


2  

Please explain your query so that can come up with specific reply.

请解释您的查询,以便能够提出具体的答复。

If I am getting you right then you want to calculate standard deviation of RGB of pixel or HSV of color, you can frame your own method of standard deviation for circular quantities in case of HSV and RGB.

如果我找到了你想要计算像素的RGB或颜色的HSV的标准偏差,你可以在HSV和RGB的情况下为循环量构建自己的标准偏差方法。

We can do this by wrapping the values. For example: Average of [358, 2] degrees is (358+2)/2=180 degrees. But this is not correct because its average or mean should be 0 degrees. So we wrap 358 into -2. Now the answer is 0. So you have to apply wrapping and then you can calculate standard deviation from above link.

我们可以通过包装值来实现。例如:[358,2]度的平均值是(358 + 2)/ 2 = 180度。但这不正确,因为它的平均值或平均值应为0度。所以我们将358包装成-2。现在答案是0.所以你必须应用包装,然后你可以从上面的链接计算标准偏差。

UPDATE: Convert RGB to HSV

更新:将RGB转换为HSV

    // r,g,b values are from 0 to 1 // h = [0,360], s = [0,1], v = [0,1]
//  if s == 0, then h = -1 (undefined)

void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v )

{
 float min, max, delta;   
    min = MIN( r, MIN(g, b ));   
    max = MAX( r, MAX(g, b ));   
    *v = max;  
    delta = max - min;   
    if( max != 0 )  
        *s = delta / max;  
    else {   
        // r = g = b = 0   
        *s = 0;   
        *h = -1;   
        return; 
    }
    if( r == max )
        *h = ( g - b ) / delta; 
    else if( g == max )
        *h=2+(b-r)/delta;
    else 
        *h=4+(r-g)/delta; 
    *h *= 60;
    if( *h < 0 ) 
        *h += 360;
}

and then calculate standard deviation for hue value by this:

然后通过以下方法计算色调值的标准偏差:

double calcStddev(ArrayList<Double> angles){
  double sin = 0;
  double cos = 0;
  for(int i = 0; i < angles.size(); i++){
       sin += Math.sin(angles.get(i) * (Math.PI/180.0));
       cos += Math.cos(angles.get(i) * (Math.PI/180.0)); 
  }
  sin /= angles.size();
  cos /= angles.size();

  double stddev = Math.sqrt(-Math.log(sin*sin+cos*cos));

  return stddev;

}