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

Delphi Sources



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

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 26.08.2013, 18:05
Аватар для Speech
Speech Speech вне форума
Новичок
 
Регистрация: 16.02.2012
Сообщения: 55
Репутация: 10
По умолчанию Помогите исправить алгоритм поиска пикселя в TImage

Доброго времени суток. Скажу сразу - уже мало что соображаю, ибо долго сидел с этим кодом . Вроде и пустяк, но никак не могу развязать этот узел.
Мне надо найти определенный пиксель в компоненте TImage. Для этого я написал 2 функции.
Эта функция собственно ищет любой пиксель с заданным цветом и возвращает его координаты:
Код:
{тип на координаты курсора, будет использоваться в функции по поиску пикселя}
type
  CursorXY = record
  X   : Integer;
  Y   : Integer;
  Res : Boolean;
  end;

{функция поиска пикселя
FindColor    - цвет который будем искать
X, Y         - координаты с которых будем начинать поиск
StopX, StopY - по каким координатам будем прекращать поиск}
function FindPixel(FindColor, X, Y, StopX, StopY: Integer): CursorXY;
var
  X1    : Integer;
  Flag  : Boolean;
begin
  Result.Res:= False;
  Flag      := False;
  while Y <= StopY-1 do
    begin
      for X1:= X to StopX-1 do
        begin
          SetCursorPos(X1, Y);
          if Form1.Image1.Picture.Bitmap.Canvas.Pixels[X1, Y] = FindColor then
            begin
              Result.X    := X1;    {возвращаем координаты найденного пикселя}
              Result.Y    := Y;
              Result.Res  := True;  {а также информацию о том что пиксель найден}
              Flag        := True;  {мы нашли наш пиксель}
              Break;                {значит выходим из цикла}
            end;
        end;
      if Flag then                  {если завершили внутренний цикл - завершаем и внешний}
        Break;

      Inc(Y);
    end;
end;

Эта функция сверяет относительно найденного пикселя последующий пиксели (типа по маске), чтобы найти именно тот пиксель который мне нужен, ибо с одинаковыми цветами таких пикселей много.
Код:
const
  {массив цветов пикселей на начало фона картинки, на данной картинке это координаты 369, 226}
  ArrayAreaPhoto : array[0..30] of Integer = (13224393, 13027014, 13290186,
  12698049, 13224393, 12500670, 13158600, 12829635, 12895428, 12566463,
  12961221, 13158600, 13487565, 12829635, 13224393, 12961221, 13224393,
  13224393, 13355979, 13158600, 13290186, 13224393, 13290186, 12763842,
  13487565, 13027014, 13619151, 12895428, 13224393, 13092807, 13290186);

{функция проверки по маске}
function FindAreaPhotoEX(X, Y: integer): Boolean;
var
  i: Integer;
begin
  for i:= 0 to 30 do
    begin
      if Form1.Image1.Picture.Bitmap.Canvas.Pixels[X, Y] <> ArrayAreaPhoto[i] then
        begin
          Result:= False;
          Exit;
        end;
      Inc(X);
    end;
  Result:= True;
end;
Эти 2 функции по отдельности работают как надо. Может там конечно еще какие то нюансы алгоритма всплывут и можно будет улучшить - то дело такое. Проблема в том что не получается найти искомый пиксель, который я пытаюсь найти следующим образом:
Код:
{функция поиска начала фона под картинкой
X, Y - координаты начала поиска, обычно 0, 0
StopX, StopY - по каким координатам будем прекращать поиск}
function FindAreaPhoto(X, Y, StopX, StopY: Integer): CursorXY;
var
  CursorPosition  : CursorXY;
begin
  Result.Res      := False;
  CursorPosition.X:= X;
  CursorPosition.Y:= Y;
  while True do                   {крутим пока что вечный цикл, пока не найдем маску}
    begin
      {я думаю что ошибка в этой строке, но ума не приложу что еще не так}
      CursorPosition:= FindPixel(ArrayAreaPhoto[0], CursorPosition.X, CursorPosition.Y, StopX, StopY);

      {если первый пиксель найден - проверяем маску}
      if CursorPosition.Res and (CursorPosition.X < StopX-30) then
        begin
                                  {Если нашли маску - завершаем работу функции}
          if FindAreaPhotoEX(CursorPosition.X, CursorPosition.Y) then
            begin                 {но сюда мы почему то никогда не попадаем!}
              Result.X    := CursorPosition.X;
              Result.Y    := CursorPosition.Y;
              Result.Res  := True;
              Exit;
            end;
          Inc(CursorPosition.X);  {нам же в другой раз нужен следующий пиксель по координате X}
        end;
    end;
end;
Одним словом - я запутался. Прилагаю готовый проект, который можно скачать ниже. Перед тем как запускать, закоментируйте строку 70 SetCursorPos(X1, Y);, ибо будет по экрану самопроизвольно бегать мышка. Сделал для наглядности. Либо тогда останавливать проект горячими клавишами.
Вложения
Тип файла: rar test-project.rar (678.0 Кбайт, 3 просмотров)
Ответить с цитированием
  #2  
Старый 26.08.2013, 22:01
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Код:
      Flag        := True;  {мы нашли наш пиксель}
      Break;                {значит выходим из цикла}
    end;
  end;
  if Flag then                  {если завершили внутренний цикл - завершаем и внешний}
    Break; 
Первое на что обратил внимание. Достаточно:
Код:
      Flag        := True;  {мы нашли наш пиксель}
      Exit;                {значит выходим из функции}
    end;
  end;
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
Speech (26.08.2013)
  #3  
Старый 26.08.2013, 22:57
Аватар для Speech
Speech Speech вне форума
Новичок
 
Регистрация: 16.02.2012
Сообщения: 55
Репутация: 10
По умолчанию

angvelem, спасибо конечно за поправку. Но если бы кто подсказал как найти тот пиксель с координатами 369, 226 - было бы здорово
Ответить с цитированием
  #4  
Старый 26.08.2013, 23:09
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Пока архив не смотрел.

Разберись с
Код:
function FindAreaPhotoEX(X, Y : Integer) : Boolean;
var
  I : Integer;
begin
  Result := False;

  for I := 0 to 30 do
  begin
    if Form1.Image1.Picture.Bitmap.Canvas.Pixels[X, Y] <> ArrayAreaPhoto[i] then
      Exit;
    Inc(X);
  end;

  Result := True;
end;
X наращивается локально или нужно отдавать наружу увеличенным.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.

Последний раз редактировалось angvelem, 26.08.2013 в 23:31.
Ответить с цитированием
  #5  
Старый 27.08.2013, 00:01
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Код:
function FindAreaPhoto(X, Y, StopX, StopY : Integer) : CursorXY;
begin
...
    // Возвращает найденную позицию, к примеру 1310 по X
    CursorPosition := FindPixel(ArrayAreaPhoto[0], CursorPosition.X, CursorPosition.Y, StopX, StopY);
...
      // наращивает, но в следующем цикле, FindPixel опять вернёт 1310
      // и так до бесконечности
      Inc(CursorPosition.X);  {нам же в другой раз нужен следующий пиксель по координате X}
...
end;
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #6  
Старый 27.08.2013, 00:44
Аватар для Speech
Speech Speech вне форума
Новичок
 
Регистрация: 16.02.2012
Сообщения: 55
Репутация: 10
По умолчанию

Цитата:
Сообщение от angvelem
Пока архив не смотрел.

Разберись с
Код:
function FindAreaPhotoEX(X, Y : Integer) : Boolean;
var
  I : Integer;
begin
  Result := False;

  for I := 0 to 30 do
  begin
    if Form1.Image1.Picture.Bitmap.Canvas.Pixels[X, Y] <> ArrayAreaPhoto[i] then
      Exit;
    Inc(X);
  end;

  Result := True;
end;
X наращивается локально или нужно отдавать наружу увеличенным.
Локально, там же в функцию передается не в виде var. Массив ArrayAreaPhoto глобальный. Наружу отдается True если прошли все совпадения по пикселям.
Ответить с цитированием
  #7  
Старый 27.08.2013, 00:51
Аватар для Speech
Speech Speech вне форума
Новичок
 
Регистрация: 16.02.2012
Сообщения: 55
Репутация: 10
По умолчанию

Цитата:
Сообщение от angvelem
Код:
function FindAreaPhoto(X, Y, StopX, StopY : Integer) : CursorXY;
begin
...
    // Возвращает найденную позицию, к примеру 1310 по X
    CursorPosition := FindPixel(ArrayAreaPhoto[0], CursorPosition.X, CursorPosition.Y, StopX, StopY);
...
      // наращивает, но в следующем цикле, FindPixel опять вернёт 1310
      // и так до бесконечности
      Inc(CursorPosition.X);  {нам же в другой раз нужен следующий пиксель по координате X}
...
end;
Вот - знаю же что именно тут ошибка. Но никак ее не могу увидеть. Да, действительно цикл получается до бесконечности, но! Я же увеличиваю переменную CursorPosition.X на 1, специально чтобы избежать бесконечного цикла и оставить проверенный пиксель далеко позади. И в дебаггере смотрел - там действительно становится 1311. Но в тоже время никак не соображу - как правильно записать? Может поможете конкретным примером? А то я просто не вижу этой ошибки ))
Ответить с цитированием
  #8  
Старый 27.08.2013, 01:18
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Так нужно найти отдельный пиксел или всю группу?
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #9  
Старый 27.08.2013, 01:23
Аватар для Speech
Speech Speech вне форума
Новичок
 
Регистрация: 16.02.2012
Сообщения: 55
Репутация: 10
По умолчанию

На той картинке что в архиве нужно найти пиксель с координатами 369, 226.
Дело в том что пикселей с таким цветом много, и я взял последовательность группы пикселей (30 штук, что в массиве). Но эта последовательность мне нужна лишь чтобы подтвердить что первый пиксель этой группы - именно тот что мне нужен.
Ответить с цитированием
  #10  
Старый 27.08.2013, 01:24
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Если так, то по этой координате другой цвет, а именно $CBCBCB (13355979).

А нет, всё верно. Забыл что отсчёт идёт снизу.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.

Последний раз редактировалось angvelem, 27.08.2013 в 01:29.
Ответить с цитированием
  #11  
Старый 27.08.2013, 01:34
Аватар для Speech
Speech Speech вне форума
Новичок
 
Регистрация: 16.02.2012
Сообщения: 55
Репутация: 10
По умолчанию

А у меня показывает 13224393. Закомментируйте строку
Код:
CursorPosition:= FindAreaPhoto(0, 0, Image1.Width, Image1.Height);
Потом аккуратно наведите мышкой на координаты 369, 226 и в Edit1 будет цвет, который под курсором мышки. Я ориентировался по этому, а как вы определили по тех координатах цвет 13355979?
Ответить с цитированием
  #12  
Старый 27.08.2013, 01:37
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Я смотрел координаты в графическом редакторе. Если считать снизу картинки, то тогда нужный цвет существует по указанным координатам.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #13  
Старый 27.08.2013, 01:51
Аватар для Speech
Speech Speech вне форума
Новичок
 
Регистрация: 16.02.2012
Сообщения: 55
Репутация: 10
По умолчанию

Странно получается - ведь все координаты на компьютере идут с левого верхнего угла монитора!
Ладно, цвет цветом. Можете более детально объяснить насчет этого участка кода?
Цитата:
Сообщение от angvelem
Код:
function FindAreaPhoto(X, Y, StopX, StopY : Integer) : CursorXY;
begin
...
    // Возвращает найденную позицию, к примеру 1310 по X
    CursorPosition := FindPixel(ArrayAreaPhoto[0], CursorPosition.X, CursorPosition.Y, StopX, StopY);
...
      // наращивает, но в следующем цикле, FindPixel опять вернёт 1310
      // и так до бесконечности
      Inc(CursorPosition.X);  {нам же в другой раз нужен следующий пиксель по координате X}
...
end;
Как правильно записать?
Ответить с цитированием
  #14  
Старый 27.08.2013, 01:55
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

У битмапов с нижнего левого.
Сейчас уже поздно (или рано), днём посмотрю.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
Speech (27.08.2013)
  #15  
Старый 27.08.2013, 02:37
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Поиск подправил, но искомая комбинация не найдена.
Вложения
Тип файла: rar speech.rar (8.7 Кбайт, 8 просмотров)
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
Speech (27.08.2013)
Ответ


Delphi Sources

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

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

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

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


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


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

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

ВКонтакте   Facebook   Twitter