Быстрая формула для “высококонтрастной” кривой

Как насчет того, чтобы определить произвольное разрешение для Вашего пространства, и вычисляют для каждой точки в той матрице, мере расстояния от той точки до всех точек, тогда Вы могли сделать "график тепла" и использовать порог для определения кластеров.

Это - хорошее осуществление для обработки, возможно, позже я отправлю решение.

РЕДАКТИРОВАНИЕ:

Здесь это:

//load the image
PImage sample;
sample = loadImage("test.png");
size(sample.width, sample.height);
image(sample, 0, 0);
int[][] heat = new int[width][height];

//parameters
int resolution = 5; //distance between points in the gridq
int distance = 8; //distance at wich two points are considered near
float threshold = 0.5;
int level = 240; //leven to detect the dots
int sensitivity = 1; //how much does each dot matters

//calculate the "heat" on each point of the grid
color black = color(0,0,0);
loadPixels();
for(int a=0; a<width; a+=resolution){
  for(int b=0; b<height; b+=resolution){
    for(int x=0; x<width; x++){
      for(int y=0; y<height; y++){
        color c = sample.pixels[y*sample.width+x];        
        /**
         * the heat should be a function of the brightness and the distance, 
         * but this works (tm)
         */
        if(brightness(c)<level && dist(x,y,a,b)<distance){
          heat[a][b] += sensitivity;
        }
      }
    }
  }
}

//render the output
for(int a=0; a<width; ++a){
  for(int b=0; b<height; ++b){
    pixels[b*sample.width+a] = color(heat[a][b],0,0);
  }
}
updatePixels();
filter(THRESHOLD,threshold);

РЕДАКТИРОВАНИЕ 2 (немного менее неэффективный код, но тот же вывод):

//load the image
PImage sample;
sample = loadImage("test.png");
size(sample.width, sample.height);
image(sample, 0, 0);
int[][] heat = new int[width][height];
int dotQ = 0;
int[][] dots = new int[width*height][2];
int X = 0;
int Y = 1;


//parameters
int resolution = 1; //distance between points in the grid
int distance = 20; //distance at wich two points are considered near
float threshold = 0.6;
int level = 240; //minimum brightness to detect the dots
int sensitivity = 1; //how much does each dot matters

//detect all dots in the sample
loadPixels();
for(int x=0; x<width; x++){
 for(int y=0; y<height; y++){
   color c = pixels[y*sample.width+x];
   if(brightness(c)<level) {
       dots[dotQ][X] += x;
       dots[dotQ++][Y] += y;
   }
 }
}

//calculate heat
for(int x=0; x<width; x+=resolution){
 for(int y=0; y<height; y+=resolution){
   for(int d=0; d<dotQ; d++){
     if(dist(x,y,dots[d][X],dots[d][Y]) < distance)
       heat[x][y]+=sensitivity;
   }
 }
}

//render the output
for(int a=0; a<width; ++a){
 for(int b=0; b<height; ++b){
   pixels[b*sample.width+a] = color(heat[a][b],0,0);
 }
}
updatePixels();
filter(THRESHOLD,threshold);

/** This smooths the ouput with low resolutions
* for(int i=0; i<10; ++i) filter(DILATE);
* for(int i=0; i<3; ++i) filter(BLUR);
* filter(THRESHOLD);
*/

И вывод с (уменьшенный) Кентский образец:

5
задан Spooky 20 June 2015 в 18:26
поделиться

3 ответа

Тривиально вы можете просто установить порог, но я полагаю, что это слишком глупо:

return i < 0.5 ? 0.0 : 1.0;

Поскольку вы упоминаете «увеличение контрастности», я предполагаю, что входные значения являются значениями яркости. Если это так, и они дискретны (возможно, это 8-битное значение), вы можете использовать таблицу поиска, чтобы сделать это довольно быстро.

Ваш 'mulContrastize' выглядит достаточно быстро. Одним из вариантов оптимизации было бы использование целочисленной математики. Скажем, опять же, ваши входные значения могут быть фактически переданы как 8-битное беззнаковое значение в [0..255]. (Опять же, возможно, хорошее предположение?) Вы могли бы сделать что-то примерно вроде ...

int mulContrastize(int i) {
  if (i < 128) return (i * i) >> 7; 
  // The shift is really: * 2 / 256
  i = 255 - i;
  return 255 - ((i * i) >> 7);
5
ответ дан 18 December 2019 в 07:10
поделиться

Рассмотрим следующие сигмоидальные -образные функции (правильно переведенные в желаемый диапазон):

screenshot


Я создал приведенный выше рисунок с помощью MATLAB. Если интересно, вот код:

x = -3:.01:3;
plot(   x, 2*(x>=0)-1, ...
        x, erf(x), ...
        x, tanh(x), ...
        x, 2*normcdf(x)-1, ...
        x, 2*(1 ./ (1 + exp(-x)))-1, ...
        x, 2*((x-min(x))./range(x))-1  )
legend({'hard' 'erf' 'tanh' 'normcdf' 'logit' 'linear'})
13
ответ дан 18 December 2019 в 07:10
поделиться

Кусочная интерполяция может быть быстрой и гибкой. Это требует всего нескольких решений, за которыми следуют умножение и сложение, и может аппроксимировать любую кривую. Это также позволяет избежать естественности, которая может быть введена справочными таблицами (или дополнительных затрат на два поиска с последующей интерполяцией для сглаживания этого), хотя lut может отлично работать в вашем случае.

alt text

Всего с несколькими сегментами, вы можете получить довольно хороший матч. Здесь будет естественность цветовых градиентов , которую будет намного труднее обнаружить, чем естественность в абсолютных цветах.

Как указывает Имон Нербон в комментариях, сегментацию можно оптимизировать с помощью "choos [ ing] точки сегментации, основанные на чем-то вроде второй производной, чтобы максимизировать детализацию ", то есть где уклон меняется больше всего. Ясно, что в моем опубликованном примере наличие трех сегментов в середине пятисегментного корпуса не добавляет много деталей.

4
ответ дан 18 December 2019 в 07:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: