Проблема в реализации алгоритма медианного разреза с использованием Javascript

Я пытаюсь реализовать код, который выбирает цвета из изображения, а затем получает палитру определенных цветов из всех цветов изображения. Я пытаюсь использовать алгоритм Median Cut для реализации этого.

В настоящее время я выполняю шаги для алгоритма Median Cut, упомянутого здесь:

Вот фрагмент кода из моего POC:

const getColor = () => {
  const canvas = document.createElement('canvas');
  canvas.width = displayImage.width;
  canvas.height = displayImage.height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(displayImage, 0, 0);
  const pixelData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
  getPallete(pixelData);
};
const getPallete = (data) => {
  // data contains image data (r,g,b,a)
  if (data.length != 0) {
    for (let i = 0; i < data.length; i += 4) {
      let [red, green, blue] = [data[i], data[i + 1], data[i + 2]];

      if (red < channelProperties.minRed) {
        channelProperties.minRed = red;
      }
      if (red > channelProperties.maxRed) {
        channelProperties.maxRed = red;
      }

      // Update minimum and maximum values for green channel
      if (green < channelProperties.minGreen) {
        channelProperties.minGreen = green;
      }
      if (green > channelProperties.maxGreen) {
        channelProperties.maxGreen = green;
      }

      // Update minimum and maximum values for blue channel
      if (blue < channelProperties.minBlue) {
        channelProperties.minBlue = blue;
      }
      if (blue > channelProperties.maxBlue) {
        channelProperties.maxBlue = blue;
      }
    }
    // gets the channel with highest range
    let highestChannel = getChannel();
    //This sorts the image data based on highest channel
    let sortedData = sortImageData(data, highestChannel);
    //This gives back the middle index
    let median = getMedian(sortedData);
    //Here I break the array from median and resend it
    const lowerPart = data.slice(0, median);
    const upperPart = data.slice(median + 1);
    getPallete(lowerPart);
    getPallete(upperPart);
  }
};

Я реализовал первые 4 шага, упомянутые в ссылке. Тем не менее, я ошибаюсь на последнем шаге или, скорее, я не могу понять, как получить мой последний поддон. Может ли кто-нибудь помочь исправить этот код/рассказать мне, что я пропустил?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
77
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Похоже, вы ничего не возвращаете и, похоже, не нарушаете рекурсию. Кроме того, в связанном источнике говорится, что вы должны строить средние значения по корзинам. И вам нужно указать количество цветов для поиска, что соответствует количеству итераций.

Вот что, я думаю, вам нужно добавить:

const getPallete = (data, iterations) => {
  if (data.length === 0) {
    return []
  }
  
  if (iterations <= 1){
    return [getAverageColor(data)]  // <--- build bucket average
  }

  // build upper and lower bucket, same as before
  
  return [ // <--- collect and return recursion result
    ...getPallete(lowerPart, iterations-1),
    ...getPallete(upperPart, iterations-1)
  ]
}

const getAverageColor = (data) => {
  const sums = [0,0,0,0]
  for (let i = 0; i < data.length; i += 4) {
    for (let j = 0; j < 4; j++) {
      sums[j] += data[i+j]
    }
  }
  const numberOfPixels = data.length / 4
  return sums.map(v => Math.round(v/numberOfPixels))
}

Вот быстрая песочница

Это привело меня к тому, что я получаю значения NaN для некоторых цветов. Но, кажется, это укажет мне правильный путь. Я пытаюсь найти причину NaN прямо сейчас

Shardul Birje 12.04.2023 19:44

О, интересно. Я предполагаю, что это алгебраическая операция с undefined, вероятно, из-за доступа к индексу массива, который не установлен. Я предполагаю, что sortImageData() довольно много копирует, так что это похоже на место для поиска.

Moritz Ringler 12.04.2023 20:41

Обнаружил проблему, я пропускал средний индекс при нарезке массива (строка upperPart была неправильной). Позже это привело к undefined, поскольку цикл for в функции getAverageColor увеличивался на 4 для каждой итерации. Однако я все еще довольно далек от решения, так как получаю темные цветовые оттенки, которые не являются частью изображения.

Shardul Birje 12.04.2023 21:18

Ой, нашел ошибку в getAverageColor(), средние надо делить на data.length / 4, а не на data.length. Я думаю, именно поэтому у вас более темные оттенки (извините!).

Moritz Ringler 12.04.2023 22:48

Не беспокойтесь, ваш код уже очень помог мне, показав правильный путь вперед, большое спасибо! Что касается моего прогресса, я рефакторил свой код (почти) с нуля. Я на 90% близок к тому, что я понимаю. Завтра сейчас проверю.

Shardul Birje 12.04.2023 23:02

Другие вопросы по теме