![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
![]() Уважаемые форумчане, подскажите алгоритм решения вот такой задачки:
имеется 16-цветное bitmap-изображение с разноцветными пятнами, необходимо подсчитать площадь каждого пятна и их количество. Понятно, что площадь одного пятна можно вычислить попиксельно, с толку сбивает то, что пятен одного цвета может быть несколько и все они неправильной формы. Может кто встречал такой алгоритм? Чтоб было понятнее о чем речь, прикрепила картинку. |
#2
|
||||
|
||||
![]() Может, каким-нибудь волновым алгоритмом - пускать волну для определенного цвета з затуханием при выходе на другой цвет. Тока создать двумерный булев массив с размерностью как битмап и записывать, проходила там волна или нет. Соответственно, подсчитывать количество пикселов, по которым прошла волна - это и будет площадь. ИМХО.
Вот типа того. Но желательно, чтобы пятна были одноцветными, без "оттенков", подсчет идет строго по цвету. Или зделать небольшой припуск... Последний раз редактировалось YVitaliy, 02.02.2012 в 22:16. |
#3
|
||||
|
||||
![]() Я бы создал на каждое пятно по региону (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; Код:
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; Код:
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
|
|||
|
|||
![]() Большое спасибо за ответы. Оба алгоритма прекрасно работают, если пятно заданного цвета одно. Проблемы начинаются, когда пятен одного цвета несколько - все суммируется в общую площадь. Как же быть?
P.S. Извините, YVitaliy, не заметила добавления, сейчас попробуем... Последний раз редактировалось entropy55, 03.02.2012 в 16:17. |
#5
|
||||
|
||||
![]() Там у меня можно клик по имаге делать, соответственно справа показывает площадь и цвет пятна под курсором. И ничего не суммируется. В мемо просто выводится для примера площадь всех пятен по отдельности и суммарная.
И еще: поскольку подсчет - рекурсия, то вполне возможно переполнение стека при слишком болиших изображениях. Не проверял. Последний раз редактировалось YVitaliy, 03.02.2012 в 16:19. |
#6
|
||||
|
||||
![]() Я бы работал по регионам.
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
|
|||
|
|||
![]() Ура! Дошло! dr. F.I.N. и YVitaliy, спасибо вам большое!
|