По-пиксельный анализ картинки.

  • Автор темы xopek160183
  • Дата начала
X

xopek160183

Гость
#1
Hi всем. Появился такой вопрос: прога должная брать картинку и анализировать ее содержимое по цветам пикселей. Изначально подразумевается, что картинка серая (или в крайнем случае черно-белая). Прога должна пробегать по всем пикселям и в зависимости от их цвета оставлять соответствующие записи в лог-файле анализа картинки.
Я на форме создал paitbox и для проверки две переменные bitmap и binmap1. В первую через диалог из файла загружаю картинку и затем через scanline пытаюсь рассмотреть содержимое. Но че-то я не догоняю. Для проверки специально создал маленький рисуночек, в котором просто вертикальная толстая черная линия в середине белого фона.
Для проверки работы сделал следующее - после получения файла в bitmap, он анализируется и черные точки должны быть заменены например на красные. Кусок пробного кода:

Код:
procedure TForm1.Button1Click(Sender: TObject);
var
Bitmap, Bitmap1:Tbitmap;
x,y:integer;
p:pbytearray;
begin
bitmap:=tbitmap.Create;
bitmap1:=tbitmap.Create;
if OpenDialog1.Execute then
bitmap.LoadFromFile(opendialog1.FileName);
paintbox1.Canvas.Draw(0,0,Bitmap);
for y := 0 to BitMap.Height -1 do
begin
P := BitMap.ScanLine[y];
for x := 0 to BitMap.Width -1 do
if p[x]=clblack then
bitmap1.Canvas.Pixels[x,y]:=clred

end;
//bitmap1:=bitmap;
paintbox1.Canvas.Draw(bitmap.Width+2,0,bitmap1);

end;
Казалось бы - банальная задача, но не получается!
Я новичок в программировании на делфи и догнать не могу в сложившейся ситуации:
Значения p[x] принимают какие-то неожиданные значения (255, затем 248 и еще какие-то). И соответственно и преобразование осуществляется не то, которое должно быть. Также: Если разкоментить строку bitmap1:=bitmap, то копия рисунка рисуется рядом с первой, т.е. bitmap1 получает нормальное значение. А если она закоментирована, то ничего не выводится. Хотя если в цикле в строке bitmap1.Canvas.Pixels[x,y]:=clred убрать bitmap1 и рисовать непосредственно на канве формы, то рисунок (не тот который должен быт, но) по-точечно рисуется! Ничего понять не могу! Вечер просидел, мозг вынес, но так и не смог понять, что я не так делаю!!!
Плиз, помогите!
PS. Может есть какие-то другие варианты (алгоритмы) выполнения поставленной задачи?
 
X

xopek160183

Гость
#2
Что??!!! Никто помочь не может?????!!! :welcome:
Я вчера немного переделал - прописал в битмапе монохромную палитру и pixelformat:=pf1bit
Сделал малюсенькую картинку 4х4 пикселя и закрасил в черный цвет две средние вертикальные полосы. (файл bmp).
Но чего то я догнать не могу, значения p[x] принимают следующие значения
x 0 1 2 3 4
y
0 144 0 0 0 0
1 144 0 0 0 0
2 144 0 0 0 144
3 144 0 0 0 144

Понятно, что при x=4 значения р[x] нам не нужны, но тем не менее!
Народ, объясните, плз, что это за фигня? Как определить цвет конкретной точки?
 
09.11.2009
665
1
#3
Дело в том что если делать через P := BitMap.ScanLine[y]; то оно просто так(в чистом виде(p[x]=clblack) немного кривовато(там возвращаемый масив напрямую зависть от pixelformat)).
Лучше сделать через обычный канвас(дольше,но проверять на привальность легче, а когда всё правильно будет работать то можно сделать и через ScanLine):
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
Bitmap, Bitmap1:Tbitmap;
x,y:integer;

begin
if OpenDialog1.Execute then
begin
bitmap:=tbitmap.Create;
bitmap1:=tbitmap.Create;
bitmap.LoadFromFile(opendialog1.FileName);
bitmap1.width:=bitmap.width;
bitmap1.Height:=bitmap.Height;
paintbox1.Canvas.Draw(0,0,Bitmap);
for y := 0 to BitMap.Height -1 do
for x := 0 to BitMap.Width -1 do
if BitMap.canvas.Pixels[x,y]=clblack then 
bitmap1.Canvas.Pixels[x,y]:=clred else bitmap1.Canvas.Pixels[x,y]:=clwhite;

end;
paintbox1.Canvas.Draw(bitmap.Width+2,0,bitmap1);
bitmap.free;
bitmap1.free;
end;

end;
 
X

xopek160183

Гость
#4
Спасибо! Попробую!
Да! Все гуд! Так пошло! Следом еще вопрос! Если картинка будет не черно-белая, а серая - как будут делиться серые оттенки? Т.е какие значения будет принимать pixels[x,y] ? Мне большая глубина цвета не нужна. Максимум несколько оттенков - пока 2-4. (объясню зачем - делаю обработку графики для рассчета программы для ЧПУ гравировки на основе растрового рисунка. В зависимости от оттенка будет та или иная глубина фрезерования)
 
09.11.2009
665
1
#5
pixels[x,y] возвращает цвет в виде TColor,а не r g b по отдельности.
Код:
var r,g,b:byte;
begin
r:=getRvalue(image1.canvas.pixels[x,y]);// значение красного
g:=getGvalue(image1.canvas.pixels[x,y]);// зелёного
b:=getBvalue(image1.canvas.pixels[x,y]);// синего
end;
Если картинка будет не черно-белая, а серая - как будут делиться серые оттенки? Т.е какие значения будет принимать pixels[x,y] ?
r,g,b примерно равные