Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Что делать елси не хватает стэка?

35K
15 марта 2008 года
rom@rio
6 / / 09.03.2008
Есть рекурсивная функция которая проверяет цвет пикселя(x и y передаются как параметры),если цвет например черный то добавляем точку в ArrayList и вызываем эту же функцию только с координатами соседних пикселей(8 вызовов,с сооств проверками).Вся проблема в том что эта функция будет работать только в случае маленькой области черных точек!!!!!если же это оказалась большая область то программа прекращает рабоать и выдает такое сообщение:"An unhandled exception of type 'System.StackOverflowException' occurred in EditImage.exe"!я так понимаю это означает переполнение стэка!!
Кто знает подскажите как быть в таком случае???
Спасибо!
1
15 марта 2008 года
kot_
7.3K / / 20.01.2000
Угу. Так же можно потребовать от пользователя увеличения мощности компьютера, изменения архитектуры процессора и еще мирового господства на закуску. :)
Не лучше ли, для начала, оптимизировать свой алгоритм - если если для относительно несложной задачи вам не хватает размера стека в один мегабайт - то наверное в "консерватории надо чтото подправить"?
Кроме того - если черные пикснли расположены разрежено на большой области - ошибка возникает тоже?
5
15 марта 2008 года
hardcase
4.5K / / 09.08.2005
Можно воспользоваться утиллитой EditBin.exe и указать размер стека руками, так как компилятор не позволяет этого сделать.
Тут есть пример.
1
15 марта 2008 года
kot_
7.3K / / 20.01.2000
В догонку
Кстати даже если проверка выполняется с середины изображения и пиксели проверяются последовательно - то восемь проверок надо делать только один раз - на первом. Если же поиск пикселей начинается с края картинки - то восемь проверок не может быть никак. Наверняка один и тот же пиксель попадает в массив многократно.
35K
15 марта 2008 года
rom@rio
6 / / 09.03.2008
По поводу попадания одного итого же пикселя в массив:перед тем как проверить его цвет я проверяю существует ли такой писель (в смысле его координаты) в массив!
1
15 марта 2008 года
kot_
7.3K / / 20.01.2000
Цитата: rom@rio
По поводу попадания одного итого же пикселя в массив:перед тем как проверить его цвет я проверяю существует ли такой писель (в смысле его координаты) в массив!


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

35K
15 марта 2008 года
rom@rio
6 / / 09.03.2008
private void checkPixel(int x, int y)
{
Point point = new Point(x, y);
if (!ColorRegion.Contains(point))
{
if (bitmap.GetPixel(x, y).ToArgb() == Color.Black.ToArgb())
{
ColorRegion.Add(point);
if (x - 1 >= 0 & y - 1 >= 0) this.checkPixel(x - 1, y - 1);//верхний левый угол
if (y - 1 >= 0) checkPixel(x, y - 1);
if (x + 1< bitmap.Width & y - 1 >= 0) checkPixel(x + 1, y - 1);//верхний правый угол
if (x + 1 < bitmap.Width) checkPixel(x + 1, y);
if (x + 1 < bitmap.Width & y + 1 < bitmap.Height) checkPixel(x + 1, y + 1);//нижний правый угол
if (y + 1 < bitmap.Height) checkPixel(x , y + 1);
if (x - 1 >= 0 & y + 1 < bitmap.Height) checkPixel(x - 1, y + 1);//нужний левый угол
if (x - 1 >= 0) checkPixel(x-1, y);
}
}
}
1
16 марта 2008 года
kot_
7.3K / / 20.01.2000
Цитата: rom@rio
private void checkPixel(int x, int y)
{
Point point = new Point(x, y);
if (!ColorRegion.Contains(point))
{
if (bitmap.GetPixel(x, y).ToArgb() == Color.Black.ToArgb())
{
ColorRegion.Add(point);
if (x - 1 >= 0 & y - 1 >= 0) this.checkPixel(x - 1, y - 1);//верхний левый угол
if (y - 1 >= 0) checkPixel(x, y - 1);
if (x + 1< bitmap.Width & y - 1 >= 0) checkPixel(x + 1, y - 1);//верхний правый угол
if (x + 1 < bitmap.Width) checkPixel(x + 1, y);
if (x + 1 < bitmap.Width & y + 1 < bitmap.Height) checkPixel(x + 1, y + 1);//нижний правый угол
if (y + 1 < bitmap.Height) checkPixel(x , y + 1);
if (x - 1 >= 0 & y + 1 < bitmap.Height) checkPixel(x - 1, y + 1);//нужний левый угол
if (x - 1 >= 0) checkPixel(x-1, y);
}
}
}



Ой как все запущено.
Почему вы не используете посточное сканирование? Зачем все эти сложности? Ваша ошибка заключается в том что вы создаете неконтролируемую рекурсию - и естественно вы получаете переполнение стека. Вызвав в первый раз функцию и выделив память под point вы не освободите ее до тех пор, пока все пиксели не будут обработаны (или размер стека исчерпан - что у вас собственно и происходит) - это особенность рекурсивной функции.
Почему не сделать это так:

Код:
void checkPixel(int x, int y){
 if (bitmap.GetPixel(x, y).ToArgb() == Color.Black.ToArgb()) {
//Тут разбирайтесь сами надо вам указатель или нет
                    Point point(x, y);
                    ColorRegion.Add(&point);
                }
 }
void scanPixel(){
 for(int y =0;y < bitmap.Height;y++){
  for(int x=0;x < bitmap.Width;x++)
   checkPixel(x, y);
 }
}

или если вам так уж важна рекурсия:
Код:
void checkPixel(int x, int y){
 if (bitmap.GetPixel(x, y).ToArgb() == Color.Black.ToArgb()) {
//Тут разбирайтесь сами надо вам указатель или нет
                    Point point(x, y);
                    ColorRegion.Add(&point);
                }
 if(x < bitmap.Width)
  checkPixel(x+1,y);
 else if(y < bitmap.Height){
   x =0;
   checkPixel(x,y+1);
  }
return;
 }

Код не тестировался так что со всеми возможными ошибками разбирайтесь сами.
З.Ы. Используйте средства форматирования кода - небрежное оформление сообщений, признак неуважения к тем, кто вашу кашу читает.
1
16 марта 2008 года
kot_
7.3K / / 20.01.2000
В последнем моем примере вложенность рекурсии может быть черезмерно большой - так что может быть работать и будет - но это тоже не лучшее решение.
35K
17 марта 2008 года
rom@rio
6 / / 09.03.2008
Да мне все равно с рекурсией или нет!
В твоих примерах и вижу перебор всех пикселей на черный цвет!
Но дело в том что мне надо выделить черную область(произвольной формы) и именно по этому я проверяю все соседние пиксели!!!!
Если есть другие алгоритмы получения множества пикселей представляющих область опр. цвета то ПОЖАЛУЙСТА ПРЕДЛОЖИТЕ!
5
17 марта 2008 года
hardcase
4.5K / / 09.08.2005
Цитата: rom@rio
мне надо выделить черную область(произвольной формы)


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

Код:
public static List<Point> Extract(Bitmap bmp, int color) {
    List<Point> buffer = new List<Point>();
    int width = bmp.Width;
    int height = bmp.Height;
    bool into_figure = false;
    Point next_point = new Point(0, 0);
    Point prev_point = new Point(0, 0);
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            prev_point = next_point;
            next_point = new Point(x, y);
            int cur_color = bmp.GetPixel(x, y).ToArgb();
            if (cur_color == color) {
                if (!into_figure) {
                    buffer.Add(next_point); // начало последовательности
                    into_figure = true;
                }
            } else {
                if (into_figure) {
                    buffer.Add(prev_point); // конец последовательности
                    into_figure = false;
                }
            }
        }
        if (into_figure) {
            buffer.Add(next_point); // устанавливаем конец последовательности
                 // так как она дошла до края картинки
            into_figure = false;
        }
    }
    return buffer;
}
Из полученного списка можно восстановить картинку подобным образом:
Код:
Color color = Color.Black;
using (Bitmap bmp = Bitmap.FromFile("sample.bmp") as Bitmap) { // загружаем тестовую картинку
    Bitmap result = new Bitmap(bmp.Width, bmp.Height); //в этот битмап будем рисовать
    using (Graphics gfx = Graphics.FromImage(result))
    using (Pen pen = new Pen(color)) { // да-да карандашик нада создавать =)
        List<Point> points = Extract(bmp, color.ToArgb()); // обрабатываем входное изображение
        for (int i = 0; i < points.Count; i += 2) {
            Point first = points;
            Point last = points[i + 1];
            gfx.DrawLine(pen, first, last);
        }
    }
    pictureBox1.Image = result;
}
1
17 марта 2008 года
kot_
7.3K / / 20.01.2000
Цитата: rom@rio
Да мне все равно с рекурсией или нет!
В твоих примерах и вижу перебор всех пикселей на черный цвет!
Но дело в том что мне надо выделить черную область(произвольной формы) и именно по этому я проверяю все соседние пиксели!!!!
Если есть другие алгоритмы получения множества пикселей представляющих область опр. цвета то ПОЖАЛУЙСТА ПРЕДЛОЖИТЕ!


Во первых не кричите. Алгоритм который вам нужен - называется "алгоритм пьяницы" - гуглите и обрящите.
З.Ы. И советую медетировать на мою подпись - потому как хамов - орущих и требующих на на дух не перевариваю. Еще один подобный эксцесс забаню нафиг. Тема закрыта.

276
17 марта 2008 года
Rebbit
1.1K / / 01.08.2005
Цитата: kot_
Тема закрыта.


Как же закрыта если я дописываю :)

Автору. Рекурсия - зло. Ничто не мешает вам избавится от рекурсии и сделать тоже самое цыклом. И стек жрать не надо и памяти меньше уйдет.

1
17 марта 2008 года
kot_
7.3K / / 20.01.2000
Цитата: Rebbit
Как же закрыта если я дописываю :)

Автору. Рекурсия - зло. Ничто не мешает вам избавится от рекурсии и сделать тоже самое цыклом. И стек жрать не надо и памяти меньше уйдет.


:) забыл галку поставить. теперь закрыта.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог