привет всем!
есть совсем глупый вопрос, подскажите сампл простой который иллюстрирует subj. А то читаю книгу, всё здорово написано, но с примерами беда и порой трудно понять смысл не попробовав руками.
Здравствуйте, Denis, Вы писали:
D>есть совсем глупый вопрос, подскажите сампл простой который иллюстрирует subj.
Я пользуюсь следующей функцией:
Функция выравнивает гистограмму заданной прямоугольной области изображения. По рассчитанной гистограмме вычисляется дискретная функция распределения, в табличном представлении. Данная функция преобразует яркость изображения таким образом, чтобы гистограмма преобразованного поля была максимально приближена к равномерной. Далее для каждого пикселя изображения, его значение считается индексом в массиве табличного представления функции преобразования, и заменяется на выбранное в ней значение. Алгоритм функции взят из В. Яншин, Г. Калинин "Обработка изображений на языке Си для IBM PC. Алгоритмы и программы", Мир, 1994г. с 88-89.
// Для простоты считаем что работаем с 8-битным изображением
// m_ChannelSize- размер изображения
// m_pActiveChannel - массив пикселей изобрженияlong pHist[256];//Гистограмма исходного изображения
//очищаем гистограммуfor (int i=0; i< 255; i++)
pHist[i] = 0;
// Вычисляем гистограммуfor (i=0; i< m_ChannelSize; i++)
pHist[m_pActiveChannel[i]]++;
int ;
long pHistNew[256];
int Derr;
DWORD Vg, SumDes, SumFct=0;
BYTE Fns[256];// функция табличного преобразования
Vg=0;
for(i=255; i>=0; i--)
{
Vg += pHist[i];
pHistNew[i]=0;
}
//Вычисляем функцию распределения вероятности, апроксимруя ее
//выражением P(x)=sum H(i),i=0..x где H- массив гистограммыfor(i=255; i>=0; i--)
Vg -= (pHistNew[i] = Vg/(i+1));
SumDes = pHistNew[0];
// Вычисляем функцию табличного преобразованияfor (i=0, j=0; j<=255; )
{
Derr=SumDes-SumFct;
if (pHist[j]<= 2*Derr)
{
SumFct += pHist[j];
Fns[j++]=i;
}
else
{
Fns[j]=i++;
if (i <= 255)
SumDes += pHistNew[i];
}
}
// Вычисляем границы гистограммы исходного изображенияfor (j=255; pHist[j]==0; j--);
for (i=0; pHist[i]==0; i++);
if (j-i > 255)
{
Fns[0]=0;
Fns[r]=255;
}
// Вычисляем новое значение каждого пикселя по табличной функцииfor (i=0; i< m_ChannelSize; i++)
m_pActiveChannel[i]=Fns[m_pActiveChannel[i]];
В книге Crane R., Simplified approach to image processing in C (PH, 1997)(ISBN 0132264161), p.49 приведен другой алгоритм:
/***************************************************************************
* Func: histogram_equalize *
* *
* Desc: histogram equalize an input image and write it out *
* *
* Params: buffer - pointer to image in memory *
* number_of_pixels - total number of pixels in image *
***************************************************************************/void histogram_equalize(image_ptr buffer, unsigned long number_of_pixels)
{
unsigned long histogram[256]; /* image histogram */unsigned long sum_hist[256]; /* sum of histogram elements */float scale_factor; /* normalized scale factor */unsigned long i; /* index variable */unsigned long sum; /* variable used to increment sum of hist */
/* clear histogram to 0 */for(i=0; i<256; i++)
histogram[i]=0;
/* calculate histogram */for(i=0; i<number_of_pixels; i++)
histogram[buffer[i]]++;
/* calculate normalized sum of hist */
sum = 0;
scale_factor = 255.0 / number_of_pixels;
for(i=0; i<256; i++)
{
sum += histogram[i];
sum_hist[i] = (sum * scale_factor) + 0.5;
}
/* transform image using new sum_hist as a LUT */for(i=0; i<number_of_pixels; i++)
buffer[i] = sum_hist[buffer[i]];
}
Здравствуйте, Lafkadio, Вы писали:
L>Я пользуюсь следующей функцией: L>Функция выравнивает гистограмму заданной прямоугольной области изображения. По рассчитанной гистограмме вычисляется дискретная функция распределения, в табличном представлении. Данная функция преобразует яркость изображения таким образом, чтобы гистограмма преобразованного поля была максимально приближена к равномерной. Далее для каждого пикселя изображения, его значение считается индексом в массиве табличного представления функции преобразования, и заменяется на выбранное в ней значение. Алгоритм функции взят из В. Яншин, Г. Калинин "Обработка изображений на языке Си для IBM PC. Алгоритмы и программы", Мир, 1994г. с 88-89.
Спасибо за этот исходник, но вы не могли бы пояснить подробнее, что откуда берется. (Я только про этот метод, второй везде описывается — с ним просто). Кстати, есть и по коду вопросы:
L>
L> // Для простоты считаем что работаем с 8-битным изображением
L> // m_ChannelSize- размер изображения
L> // m_pActiveChannel - массив пикселей изобржения
L> long pHist[256];//Гистограмма исходного изображения
L> //очищаем гистограмму
L> for (int i=0; i< 255; i++)
L> pHist[i] = 0;
L> // Вычисляем гистограмму
L> for (i=0; i< m_ChannelSize; i++)
L> pHist[m_pActiveChannel[i]]++;
L> int ;
L> long pHistNew[256];
L> int Derr;
L> DWORD Vg, SumDes, SumFct=0;
L> BYTE Fns[256];// функция табличного преобразования
L> Vg=0;
L> for(i=255; i>=0; i--)
L> {
L> Vg += pHist[i];
L> pHistNew[i]=0;
L> }
L> //Вычисляем функцию распределения вероятности, апроксимруя ее
L> //выражением P(x)=sum H(i),i=0..x где H- массив гистограммы
L> for(i=255; i>=0; i--)
L> Vg -= (pHistNew[i] = Vg/(i+1));
L> SumDes = pHistNew[0];
L> // Вычисляем функцию табличного преобразования
L> for (i=0, j=0; j<=255; )
L> {
L> Derr=SumDes-SumFct;
L> if (pHist[j]<= 2*Derr)
L> {
L> SumFct += pHist[j];
L> Fns[j++]=i;
L> }
L> else
L> {
L> Fns[j]=i++;
L> if (i <= 255)
L> SumDes += pHistNew[i];
L> }
L> }
L> // Вычисляем границы гистограммы исходного изображения
L> for (j=255; pHist[j]==0; j--);
L> for (i=0; pHist[i]==0; i++);
L> if (j-i > 255)
L> {
L> Fns[0]=0;
L> Fns[r]=255;
L> }
Зачем этот кусок, ведь в if мы никогда не попадаем...
L> // Вычисляем новое значение каждого пикселя по табличной функции
L> for (i=0; i< m_ChannelSize; i++)
L> m_pActiveChannel[i]=Fns[m_pActiveChannel[i]];
L>
L>> if (j-i > 255) L>> { L>> Fns[0]=0; L>> Fns[r]=255; L>> }[/b] R>Зачем этот кусок, ведь в if мы никогда не попадаем...
Согласен, можно убрать. это просто осталось от исходного кода Яншина и Калинина, они не только выравнивали гистограмму но и одновременно масштабировали ее в пределах Umin и Umax. Публикую целиком раздел посвященный выравниванию гистограммы.
Как говорилось выше, необходимо «развязать» между собой диапазон уровней исходного изображения и диапазон уровней, воспроизводимых на экране программами тонового вывода. Для этого мы используем функциональное преобразование уровня.
Для нахождения требуемой функции служит подпрограмма KIPJAR (листинг 2.8). Искомая функция находится посредством сопоставления гистограммы исходного изображения с гистограммой, которую должно иметь преобразованное изображение в идеальном случае. Для получения гистограммы исходного изображения вызывается подпрограмма KIMHIS. Здесь мы несколько забегаем вперед, так как эта подпрограмма рассматривается только в следующей главе (что не мешает нам воспользоваться ей). В качестве желаемой берется равномерная гистограмма; при необходимости можно задать любую другую. Функция преобразования получается из условия пошаговой минимизации отклонения гистограммы преобразованного изображения от требуемой формы. Подпрограмма KIPJAR имеет 6 параметров. Это исходное изображение, его размеры, минимальный и максимальный уровень преобразованного поля и массив, в который помещается (в табличной форме) найденная функция. Подпрограммы KIPIMA и KIPIMD дают примеры использования полученной функции.
void KIPJAR (Image, Ni, Nj, Umin, Umax, Fns)
SHOW Image[];
int Ni, Nj, Umin, Umax;
int Fns; //Fns[0:MURMAX]
/* Получение таблично заданной функции Fns[]
преобразующей яркость изображения таким образом,
чтобы гистограмма преобразованного поля была
максимально приближена к равномерной.
Беспоисковый локально-оптимальный алгоритм.
Image - исходное изображение
Ni, Nj - его размеры
Umin - требуемый минимальный уровень
Umax - требуемый максимальный уровень
Fns - сформированная нелинейность
*/int u, r;
int Hold[MURMAX +1];// для прежней гистограммыint Hdes[MURMAX +1];// для желаемой гистограммыint Derr;
unsigned int Vg, SumDes, SumFct=0;
if (Umin<0 || Umin > Umax || Umax > MURMAX)
{
// Lafkdio. Выдача сообщения об ошибкеreturn;
}
KIMHIS(Image, Ni, Nj, Hold); // Получение гистограммы изображения
// Lafkadio. Приводить эту функцию не буду так как эта часть обычно сложностей не вызывает.
Vg=0;
for(u=MURMAX; u >= 0; u--)
{
Vg+= Hold[u];
Hdes[u]=0;
}
for(u=Umax; u >= Umin; u--)
{
Vg-= (Hdes[u]=Vg/ (u-Umin+1));
}
SumDes = Hdes[0];
for(u=0, r=0;r <=MURMAX;)
{
Derr=SumDes-SumFct;
if (Hold[r]<= 2*Derr)
{
SumFct+=Hold[r];
Fns[r++]=u;
}
else
{
Fns[r]=u++;
if(u<Umax)
SumDes+=Hdes[u];
}
}
}
for(r=MURMAX;Hold[r]==0;r--);
for(u=0;Hold[u]==0;u++);
if (r-u>Umax-Umin)
{
Fns[0]=Umin;
Fns[r]=Umax;
}
}
... где total — число пикселей в изображении.
Тогда возникает вопрос, зачем заводить целый массив если все его элементы одинаковы и в дальнейшем не изменяются. Поэтому я заменил его одной переменной.
Код работы с массивом оставил на случай, если придет в голову как можно задать другую (например "более подходящую") гистограмму. Но пока таких мыслей нет...
PS. Кстати, а у тебя есть книга Яншина в электронном виде?
Здравствуйте, Lafkadio, Вы писали:
L>Здравствуйте, Reunion, Вы писали: R>>PS. Кстати, а у тебя есть книга Яншина в электронном виде? L>здесь в течение 14 дней до 19:21 26.07.2005.
Спасибо!
Re[6]: sample for Histogram Equalization
От:
Аноним
Дата:
15.07.05 05:22
Оценка:
Здравствуйте, Lafkadio, Вы писали:
L>Здравствуйте, Reunion, Вы писали: R>>PS. Кстати, а у тебя есть книга Яншина в электронном виде? L>здесь в течение 14 дней до 19:21 26.07.2005.
А есть у тебя еще какие-нибудь книги по компьютерной графике? Где ты их берешь? Может сайт какой-нибудь знаешь?
Здравствуйте, Аноним, Вы писали: А>А есть у тебя еще какие-нибудь книги по компьютерной графике? Где ты их берешь? Может сайт какой-нибудь знаешь?
Раньше был сайт Kolhoz, где было выложено огромное количство научных книг, по разным направленииям от математики и физики до исскуственного интеллекта и обработки изображения. Но он закрылся или сменил доменное имя. Кое-что я успел закачать. Иногда можно найти что-нибудь на Avax, но там нужно отслеживать, так как публикации очень быстро обновляются. Иногда попадаются хорошие зарубежные книги в html-формате. Например Digital Image Processing. Ming Jiang. Но как показывает практика, прочитать все книжки невозможно, да и не нужно. Большая часть информации повторяется из книги в книгу с небольшими вариациями в материале и подходе к изложению. Лучше искать научные статьи на конкретные темы. Зачастую зарубежные авторы выкладывают свои публикации в открытый доступ.