#c# #linq #image-processing #pixel
#c# #linq #обработка изображений #пиксель
Вопрос:
Как я могу использовать linq для перечисления всех пикселей из изображения и обработки их? Например, мы имеем:
for (int i = 0; i < this.bitmap.Width; i )
{
for (int j = 0; j < this.bitmap.Height; j )
{
bitmap.SetPixel(x, y, Color.FromArgb(1, 1, 1));
}
}
Здесь мне не нужны пиксели списка, потому что я работаю сразу, используя циклы тем временем для циклов.
Однако я не уверен, смогу ли я обработать изображение с помощью linq подобным образом.
Я понимаю, что linq получает данные, поэтому я хотел бы взять пиксель из точки и каким-то образом сохранить координаты и данные о цвете этого пикселя. Мне это нужно, потому что как я смогу тогда установить пороговое значение?
Я пытался использовать struct, но на странице http://social.msdn.microsoft.com/Forums/is/linqtosql/thread/02154de8-ef32-4420-a3f6-e4e473df66ce они сказали, что linq не работает со структурой.
Возможно, мне следует использовать список, но когда я написал List<Point, Color> list
, я получил ошибку. Так что я действительно не знаю, как это сделать..
Все дело в том, чтобы оптимизировать мою функцию под этим текстом. Я прочитал в книге под названием «эффективное программирование на c #», что использование синтаксиса запроса было бы более читабельным, чем для циклов..
Это мой код, и я действительно прошу вас о помощи, как сделать его более читаемым кодом.
ps. пожалуйста, исправьте тему, если она не указана мной, извините.
private void ThreshGrayTails() {
this.tempBitmap = new Bitmap(this.bitmap); for (int i = 0; i < this.bitmap.Width; i ) { for (int j = 0; j < this.bitmap.Height; j ) { SetTempPixelInt(i, 0, j, 0, this.tempBitmap); if (this.tempPixelInt == 252 amp;amp; (j 2) < this.bitmap.Height amp;amp; (j - 2) > 0) { SetTempPixelInt(i, 0, j, -1, this.bitmap); //if pixel above has value 252 if (this.tempPixelInt == 252) { SetTempPixelInt(i, 0, j, -2, this.bitmap); //if pixel above has value 159 if (this.tempPixelInt == 159) { SetTempPixelInt(i, 0, j, 1, this.bitmap); //if pixel under has value 0 or 172 if (this.tempPixelInt == 0 || this.tempPixelInt == 172) { this.tempBitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255)); this.tempBitmap.SetPixel(i - 1, j, Color.FromArgb(255, 255, 255)); this.tempBitmap.SetPixel(i - 2, j, Color.FromArgb(255, 255, 255)); } } } } //if current pixel doesnt contain value in that list, turn it on black if (!colorsToThreshold.Contains(this.tempBitmap.GetPixel(i, j).R)) { Color newcolor = Color.FromArgb(0, 0, 0); this.tempBitmap.SetPixel(i, j, newcolor); } //if current pixel contain value in that list, turn it on white else { Color newcolor = Color.FromArgb(255, 255, 255); this.tempBitmap.SetPixel(i, j, newcolor); } } } this.bitmap = new Bitmap(this.tempBitmap); SaveImage("thresholded.bmp", this.bitmap); } private void SetTempPixelInt(int i, int pi, int j, int pj, Bitmap bitmap) { Color currentColor = bitmap.GetPixel(i pi, j pj); this.tempPixelInt = (int)(currentColor.R); }
Комментарии:
1. Почему вы хотите использовать LINQ для этого? Похоже, что ваше текущее решение с циклами намного лучше подходит для этой задачи.
Ответ №1:
Все дело в том, чтобы оптимизировать мою функцию под этим текстом
Если вы хотите повысить производительность, лучшим решением для вас было бы использовать небезопасный код для доступа к пикселям непосредственно в памяти. Для достижения этой цели вы должны использовать метод LockBits() для Bitmap. Некоторый пример быстрой обработки изображений на c # можно найти здесь: http://www.vcskicks.com/fast-image-processing.php
LINQ на самом деле не является решением такой проблемы.
Комментарии:
1. а как насчет блокировок? итак, я должен разблокировать бит, затем работать, а когда я закончу, затем заблокировать бит?
2. Когда вы блокируете биты, вы сообщаете .net, что хотите иметь прямой доступ к памяти. это дает вам указатель (как в c ) на ваше изображение. Когда вы закончите с изображением, вызовите UnlockBits(); Все четко описано на странице по ссылке, которую я вам дал. Удачи 🙂
Ответ №2:
Я думаю, что вы смотрите в неправильном направлении, когда пытаетесь улучшить код.
Пиксели на изображении недоступны как коллекция, поэтому вы не можете использовать LINQ для них из коробки. Вам нужно было бы создать что-то, что может предоставить вам пиксели в виде коллекции, чтобы использовать их в запросе. Вы можете использовать Range
метод для создания запроса, в котором вы можете получить доступ к пикселям, но это будет только медленный и сложный способ выполнения того, что вы уже делаете в своих циклах.
Статья, в которой вы прочитали, что LINQ не работает со структурами, относится к LINQ to SQL, который вы не используете. Однако использование структуры на самом деле не упростило бы использование LINQ для этого.