Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Графика и игры
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 02.02.2012, 20:08
entropy55 entropy55 вне форума
Прохожий
 
Регистрация: 02.02.2012
Сообщения: 5
Версия Delphi: 7.0/XE
Репутация: 10
По умолчанию Как вычислить площадь пятен?

Уважаемые форумчане, подскажите алгоритм решения вот такой задачки:
имеется 16-цветное bitmap-изображение с разноцветными пятнами, необходимо подсчитать площадь каждого пятна и их количество. Понятно, что площадь одного пятна можно вычислить попиксельно, с толку сбивает то, что пятен одного цвета может быть несколько и все они неправильной формы. Может кто встречал такой алгоритм?
Чтоб было понятнее о чем речь, прикрепила картинку.
Изображения
Тип файла: bmp picture.bmp (16.8 Кбайт, 19 просмотров)
Ответить с цитированием
  #2  
Старый 02.02.2012, 20:53
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Может, каким-нибудь волновым алгоритмом - пускать волну для определенного цвета з затуханием при выходе на другой цвет. Тока создать двумерный булев массив с размерностью как битмап и записывать, проходила там волна или нет. Соответственно, подсчитывать количество пикселов, по которым прошла волна - это и будет площадь. ИМХО.

Вот типа того. Но желательно, чтобы пятна были одноцветными, без "оттенков", подсчет идет строго по цвету. Или зделать небольшой припуск...
Вложения
Тип файла: rar area3.rar (188.0 Кбайт, 10 просмотров)

Последний раз редактировалось YVitaliy, 02.02.2012 в 22:16.
Ответить с цитированием
  #3  
Старый 03.02.2012, 12:31
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 663
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

Я бы создал на каждое пятно по региону (HRGN). А потом считал бы площадь региона. Функции накиданы на скорую руку, но рабочие:
1. Указываем битмап, точку, пустой регион и цвет - получите вместо пустого региона - регион пятна с указанным цветом.
Код:
procedure _Do(bmp: TBitMap; X, Y: Integer; c: TColor; var r: hRgn);
  var
    rg_T: HRgn;
  begin
    if (bmp.Canvas.Pixels[X, Y] <> c) or PtInRegion(r, X, Y) then Exit;
    rg_T := CreateRectRgn(X, Y, X + 1 , Y + 1);
    CombineRgn(r, r, rg_T, RGN_OR);
    DeleteObject(rg_T);
    if X > 0 then _DO(bmp, X - 1, Y, c, r);
    if X < bmp.Width - 1 then _DO(bmp, X + 1, Y, c, r);
    if Y > 0 then _DO(bmp, X, Y - 1, c, r);
    if Y < bmp.Height - 1 then _DO(bmp, X, Y + 1, c, r);
  end;
2. Передаем полученный выше регион и получаем его площадь в квадратных пикселях:
Код:
function RgnSquare(r: hRgn): Int64;
  type
   TRectArray = Array[0..9999] of TRect;
   PRectArray = ^TRectArray;
  var
    i: Integer;
    RgnData: PRgnData;
    RgnDataSize: DWord;
    RectArrayPtr: PRectArray;
  begin
    Result := 0;
    RgnDataSize:= GetRegionData(r, 0, nil);
    GetMem(RgnData, RgnDataSize);
    GetRegionData(r, RgnDataSize, RgnData);
    if RgnData^.rdh.nCount > 0 then
    begin
      RectArrayPtr:= @RgnData.Buffer;
      for i := 0 to RgnData^.rdh.nCount - 1 do
      with RectArrayPtr[i] do
      Result := Result + (Bottom - Top) * (Right - Left);
    end;
    FreeMem(RgnData);
  end;
3. Пример использования:
Код:
var
  c: TColor;
  rg_R: HRgn;
begin
  c := Image1.Canvas.Pixels[0, 0];
  rg_R := CreateRectRgn(0, 0, 0, 0);
  //================
  _Do(Image1.Picture.Bitmap, 0, 0, c, rg_R);
  FillRgn(Canvas.Handle, rg_R, Canvas.Pen.Handle);
  ShowMessage(IntToStr(RgnSquare(rg_R)));
  //================
  DeleteObject(rg_R);
end;
__________________
Грамотно поставленный вопрос содержит не менее 50% ответа.
Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть.
Ответить с цитированием
  #4  
Старый 03.02.2012, 16:09
entropy55 entropy55 вне форума
Прохожий
 
Регистрация: 02.02.2012
Сообщения: 5
Версия Delphi: 7.0/XE
Репутация: 10
По умолчанию

Большое спасибо за ответы. Оба алгоритма прекрасно работают, если пятно заданного цвета одно. Проблемы начинаются, когда пятен одного цвета несколько - все суммируется в общую площадь. Как же быть?
P.S. Извините, YVitaliy, не заметила добавления, сейчас попробуем...

Последний раз редактировалось entropy55, 03.02.2012 в 16:17.
Ответить с цитированием
  #5  
Старый 03.02.2012, 16:16
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

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

Последний раз редактировалось YVitaliy, 03.02.2012 в 16:19.
Ответить с цитированием
  #6  
Старый 03.02.2012, 16:18
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 663
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

Я бы работал по регионам.
1. Создем глобальный регион размером с картинку CreateRectRgn(0, 0, BitMap.Width, BitMap.Height)
2. Бегаем по строкам и столбцам битмапа
2.1 Если точка НЕ входит в глобальный регион, то идем в 2, иначе (2.2)
2.2 "выделяем пятно" от этой точки процедурой _Do из моего предыдущего поста.
2.3 Выделив регион удаляем, его из глобального

По такому алгоритму пятна никак не сольются воедино.
__________________
Грамотно поставленный вопрос содержит не менее 50% ответа.
Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть.

Последний раз редактировалось dr. F.I.N., 03.02.2012 в 16:20.
Ответить с цитированием
  #7  
Старый 03.02.2012, 17:42
entropy55 entropy55 вне форума
Прохожий
 
Регистрация: 02.02.2012
Сообщения: 5
Версия Delphi: 7.0/XE
Репутация: 10
По умолчанию

Ура! Дошло! dr. F.I.N. и YVitaliy, спасибо вам большое!
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра
Комбинированный вид Комбинированный вид

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 11:54.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025