Вы можете сделать изображение в градациях серого и затем суммировать общее значение пикселей.Затем, если вы разделите каждый пиксель на эту сумму, вы получите вес.Затем вы выбираете число от 0 до 1 и начинаете с первого взвешенного пикселя и продолжаете суммировать значения, пока не доберетесь до первого пикселя, который делает сумму больше, чем ваше случайное число.Затем раскрасьте этот пиксель на исходном изображении так, как вы хотите.
Редактировать: Psuedo Code
int imageWidth = ...
int imageHeight = ...
int[][] grayScale = ConvertImageToGrayScale(yourImage);
int totalValue = grayScale.Sum();
float[][] weightedPixels = grayScale.AsType(float[][]);
for (int y in 0...imageHeight-1)
for (int x in 0...imageWidth-1)
weightedPixels[y][x] /= totalValue;
float randomNumber = RandomReal();
float currentSum = 0;
for (int y in 0...imageHeight-1)
for (int x in 0...imageWidth-1)
currentSum += weightedPixels[y][x];
if (currentSum >= randomNumber)
break 2; // Here is your random pixel at (x, y)
Редактировать: Теория
Теория, лежащая в основе этого, заключается в том, что мы хотим преобразовать изображение в распределение вероятностей на основе яркости каждого пикселя.Таким образом, более яркие пиксели будут выбраны с большей вероятностью, чем тусклые.Преобразование в оттенки серого помогает нам генерировать PDF или weightedMatrix, уменьшая каждый пиксель до одного числа вместо тройной RGB.Мы берем сумму матрицы оттенков серого, чтобы получить общее значение, необходимое для создания взвешенной матрицы.Взвешенная матрица инициализируется матрицей оттенков серого, но затем каждый элемент делится на общий вес.Это означает, что сумма взвешенной матрицы равна 1, что является требованием для ее представления в формате PDF.Теперь мы можем выбрать случайную вероятность, которая находится между 0 и 1. Используя это, мы выбираем пиксель, суммируя по взвешенной матрице, пока сумма не станет больше, чем наша вероятность.Пиксель, на котором это происходит, является нашим случайно выбранным пикселем.Это стандартный способ случайного выбора элемента из списка с вероятностями, связанными с каждым элементом.
Редактировать: Исправление левой боковой линии
Проблема, которую принес ОПup имеет отношение к граничным условиям из цикла по массиву в Y, X строк сканирования.Если код переработан для использования линейного массива, а затем преобразовать индекс в X, пара Y, сплошная линия слева удаляется.Если средний блок основного метода изменяется на следующий, он работает как задумано:
float[] weightedPixels = ConvertImageToGrayScale(bitmap).SelectMany(r => r).ToArray();
float totalValue = weightedPixels.Sum();
for ( int i = 0; i < weightedPixels.Length; i++) {
weightedPixels[i] /= totalValue;
}
for (int pIdx = 0; pIdx < points; pIdx++)
{
double randomNumber = random.NextDouble();
double currentSum = 0;
for (int i = 0; i < weightedPixels.Length; i++)
{
currentSum += weightedPixels[i];
if (currentSum >= randomNumber)
{
int y = i / imageWidth;
int x = i % imageWidth;
bitmap.SetPixel(x, y, Color.Red);
break;
}
}
}