Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2004.05.02;
Скачать: [xml.tar.bz2];

Вниз

Оцифровка гафиков   Найти похожие ветки 

 
Галинка ©   (2004-02-03 12:29) [0]

Доброго времени суток всем, кто заглянул сегодня ко мне на ветку...

Значит теперь задача такая... Имеется файл (*.jpg) с изображением исходной сейсмограммы. Его нада загрузить в TImage и оцифровать. Т.е. раскрасить трассы разными цветами, а потом через определенный шаг по Х поднять перепендикуляры, до точек нужных цветов.

Раскрашивать кривые думаю, апроксиммируя их ломанной заданного цвета.
Цвета всех ломанных буду запоминать, наверное, в массив - TColorArray = array of TColor;

Вот вкраце суть новой заморочки... Только громко не смейтесь и сильно не плюйтесь... Мониторы всетаки ваши... :)

Заранее спасибо всем кто ответит. Если что не понятно спрашивайте.


 
Галинка ©   (2004-02-03 12:56) [1]

Для Ромкина:
Так и не так...
1) Вывести изображение;
2) Зарегистрировать его в нужной системе отсчета, типа апмлитуда - время (y-x);
3) Обвести трассы нужными цветами, запомнив цвета в какой-то структуре, ну типа массива;
4) Задать шаг оцифровки в реальных (времени) единицах, оттранслировать его в единицы изображения;
5) "Просканировать" изображение по вертикалям через deltax с целью выявления точек заданного цвета (цвета беруться из заранее сохраненной стурктуры);
6) Как только нашли точку, заносим её в динамический массив "на свое место".

Пока все.


 
Romkin ©   (2004-02-03 13:11) [2]

Мдя... Поясняю...
0. Имеется изображение в формате jpg, содержащее группу кривых, по всей видимости, представляющих собой затухающие колебания с относительно большой амплитудой, что позволяет применить к ним кусочно-линейную интерполяцию.
1. вывести изображение на экран (форму)
2. Пользователь определяет ширину и высоту изображения соответственно в единицах времени и амплитуды
3. Пользователь производит обводку каждой кривой на изображении своим цветом, пользуясь манипулятором типа "мышь" или аналогичным
4. Пользователь задает желаемый шаг оцифровки в единицах времени
5. Программа должна для каждой кривой сформировать свой массив отсчетов амплитуды через указанный шаг оцифровки. Этот массив является результатом.
Уф... Вроде все...
Теперь можно думать, обсуждать...


 
Romkin ©   (2004-02-03 13:54) [3]

Общие соображения:
1. - 2. Технически решаемо через TImage, и тд...
3. Цвета можно выбрать заранее, я думаю, это непринципиально и касается интерфейса. Обводка, думаю, должна производиться кликами мышкой по узловым точкам. Для первого приближения достаточно не делать исправления неправильного указания, это второй этап. В результате клика организуется массив TPoint, содержащий список точек в координатах изображения. Поскольку количество точек для данной кривой заранее не определено, первоначальная записть производится в односвязный список. Далее данный список переводится в массив с координатами, заданными в п.2
4. Результатом п.3 является массив множеств точек, заданных координатами (время, амплитуда). Количество данных множеств соответствует количеству кривых. Требуется сформировать для каждой кривой массив отсчетов с фиксированным шагом, вычислив значение амплитуды. Типичная задача интерполяции.
5. Итак, для каждой кривой: имеется упорядоченный массив из N элементов (время, амплитуда), причем составляющая "время" каждого последующего элемента строго больше данной составляющей предыдущего. Формируем второй массив, размером N-1, содержащий коэффициенты (a,b) аппроксимирующей прямой A = a*T + b. Далее, начав с левого отсчета, наращивая время на шаг дискретизации, для каждого отсчета по первому массиву определяется отрезок, в котороый попал отсчет, и значение амплитуды вычисляется по приведенной формуле на основе данных второго массива. В случае, если отсчет попадает точно в точку оцифровки, второй массив не используется, берется точный отсчет.
Все вроде ;)


 
Галинка ©   (2004-02-03 15:10) [4]

Для Ромкина.

А можно по-конкретнее пункт 3 из Romkin ©   (03.02.04 13:11) [2].
Потомучто как раз это пока и не получается.

Заранее спасибо.


 
xn0bys ©   (2004-02-03 16:07) [5]

Берем Image (в памяти! или лучше bitmap) запихиваем в него твой график маштабируем его как хочем, запоминаем mx, my.
Имеем 2-й image уже на форме (ВСЕГДА В МАСШТАБЕ 1:1) и копируем в него твой УЖЕ ПРОМАШТАБИРОВАННЫЙ ГРАФИК, потом уже кликаем мышкой по нашему (видимому) имиджу.


 
Romkin ©   (2004-02-03 18:17) [6]

По-конкретнее это как? :))
Вот, правда, с прорисовкой подладить надо, я целую вечность такого не делал...
Итак, кривые:
unit Curves;

interface

uses Classes, types, Graphics;

type
 PCurve = ^TCurve;
 TCurve = record
   X, Y: LongInt;
   Next: PCurve;
 end;

 PCurveHead = ^TCurveHead;
 TCurveHead = record
   Color: TColor;
   Curve: PCurve;
 end;

 TCurveArray = array of TPoint;

 TCurves = class
 private
   FCurves: TList;
   function GetCurve(Index: integer): PCurve;
   procedure FreeCurve(Index: integer);
   function GetColor(Index: integer): TColor;
   function GetCount: integer;
   procedure CheckExists(Index: integer);
   function GetLastPoint(Index: integer): TPoint;
   procedure SetColor(Index: integer; const Value: TColor);
 public
   constructor Create;
   destructor Destroy; override;
   function NewCurve: integer; //return new curve index
   //all Index is the index of curve
   procedure AddPoint(Index: integer; Point: TPoint);
   procedure DelCurve(Index: integer);
   function PointArray(Index: integer): TCurveArray;
   property Curve[Index: integer]: PCurve read GetCurve;
   property Color[Index: integer]: TColor read GetColor write SetColor;
   property LastPoint[Index: integer]: TPoint read GetLastPoint;
   property Count: integer read GetCount;
 end;

implementation

uses SysUtils;

{ TCurves }

procedure TCurves.AddPoint(Index: integer; Point: TPoint);
var
 Curve: PCurve;
begin
 CheckExists(Index);
 new(Curve);
 Curve.Next := PCurveHead(FCurves[Index])^.Curve;
 PCurveHead(FCurves[Index])^.Curve := Curve;
 Curve^.X := Point.X;
 Curve^.Y := Point.Y;
end;

constructor TCurves.Create;
begin
 inherited;
 FCurves := TList.Create;
end;

function TCurves.PointArray(Index: integer): TCurveArray;
var
 Curr: PCurve;
 i, len: integer;
begin
 Result := nil;
 Curr := GetCurve(Index);
 len := 0;
 while assigned(Curr) do
 begin
   inc(len);
   Curr := Curr^.Next;
 end;
 if len = 0 then exit;
 SetLength(Result, len);
 Curr := GetCurve(Index);
 for i := High(Result) downto Low(Result) do
   with Result[i] do
   begin
     X := Curr^.X;
     Y := Curr^.Y;
     Curr := Curr^.Next;
   end;
end;

procedure TCurves.DelCurve(Index: integer);
begin
 FreeCurve(Index);
 FCurves.Delete(Index);
end;

destructor TCurves.Destroy;
var
 i: integer;
begin
 if assigned(FCurves) then
 begin
   for i := 0 to FCurves.Count - 1 do
     FreeCurve(i);
   FCurves.Clear;
   FCurves.Free;
 end;
 inherited;
end;

procedure TCurves.FreeCurve(Index: integer);
var
 Curve, tmp: PCurve;
 CurveHead: PCurveHead;
begin
 Curve := GetCurve(Index);
 while assigned(Curve) do
 begin
   tmp := Curve;
   Curve := tmp^.Next;
   Dispose(tmp);
 end;
 CurveHead := PCurveHead(FCurves[Index]);
 if assigned(CurveHead) then
   Dispose(CurveHead);
end;

function TCurves.GetCurve(Index: integer): PCurve;
begin
 CheckExists(Index);
 Result := PCurveHead(FCurves[Index])^.Curve;
end;

function TCurves.NewCurve: integer;
var
 CurveHead: PCurveHead;
begin
 New(CurveHead);
 CurveHead^.Curve := nil;
 Result := FCurves.Add(CurveHead);
end;

function TCurves.GetColor(Index: integer): TColor;
var
 CurveHead: PCurveHead;
begin
 CheckExists(Index);
 CurveHead := PCurveHead(FCurves[Index]);
 Result := CurveHead^.Color;
end;

function TCurves.GetCount: integer;
begin
 Result := FCurves.Count;
end;

procedure TCurves.CheckExists(Index: integer);
begin
 if not assigned(FCurves[Index]) then
   raise Exception.CreateFmt("Curve with index %d not found", [Index]);
end;

function TCurves.GetLastPoint(Index: integer): TPoint;
var
 Curve: PCurve;
begin
 Result.X := 0;
 Result.Y := 0;
 Curve := GetCurve(Index);
 if assigned(Curve) then
 begin
   Result.X := Curve^.X;
   Result.Y := Curve^.Y;
 end;
end;

procedure TCurves.SetColor(Index: integer; const Value: TColor);
var
 CurveHead: PCurveHead;
begin
 CheckExists(Index);
 CurveHead := PCurveHead(FCurves[Index]);
 CurveHead^.Color := Value;
end;

end.


 
Romkin ©   (2004-02-03 18:18) [7]

Можно, конечно, все через объекты, но мне понравилось именно так :))
Теперь применение:
unit Unit2;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, jpeg, Buttons, StdCtrls, Curves;

type
 TForm2 = class(TForm)
   sbImg: TScrollBox;
   img: TImage;
   pbCurve: TPaintBox;
   SpeedButton1: TSpeedButton;
   SpeedButton2: TSpeedButton;
   Shape1: TShape;
   Shape2: TShape;
   Shape3: TShape;
   stX: TStaticText;
   stY: TStaticText;
   Label1: TLabel;
   Label2: TLabel;
   memPoints: TMemo;
   procedure FormShow(Sender: TObject);
   procedure pbCurveMouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
   procedure Shape1MouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure SpeedButton1Click(Sender: TObject);
   procedure pbCurvePaint(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure SpeedButton2Click(Sender: TObject);
   procedure pbCurveMouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
 private
   FCurves: TCurves;
   FDrawing: boolean;
   FCurveIndex: integer;
   FColor: TColor;
   FLastX: Longint;
   FLastY: Longint;
   procedure SetColor(const Value: TColor);
   procedure RepaintCurve;
   function GetCurveIndex: integer;
   procedure SetCurveIndex(const Value: integer);
   procedure ShowCurves;
   { Private declarations }
 public
   property CurveColor: TColor read FColor write SetColor;
   property CurveIndex: integer read GetCurveIndex write SetCurveIndex;
   { Public declarations }
 end;

var
 Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.FormShow(Sender: TObject);
begin
 img.Top := 0;
 img.Left := 0;
 pbCurve.Top := 0;
 pbCurve.Left := 0;
 pbCurve.Width := img.Width;
 pbCurve.Height := img.Height;
end;

procedure TForm2.SetColor(const Value: TColor);
begin
 FCurves.Color[FCurveIndex] := Value;
 RepaintCurve;
end;

procedure TForm2.RepaintCurve;
var
 CurveArray: TCurveArray;
 CurveIndex: integer;
 Rect: TRect;
begin
 Rect.Left := 0;
 Rect.Top := 0;
 Rect.Right := pbCurve.Width ;
 Rect.Bottom := pbCurve.Height;
 //pbCurve.Canvas.FillRect(Rect);
 pbCurve.canvas.Pen.Mode := pmCopy;
 for CurveIndex := 0 to FCurves.Count - 1 do
 with pbCurve.Canvas do
 begin
   Pen.Color := FCurves.Color[CurveIndex];
   CurveArray := FCurves.PointArray(CurveIndex);
   Polyline(CurveArray);
   CurveArray := nil;
 end;
end;

procedure TForm2.pbCurveMouseMove(Sender: TObject; Shift: TShiftState; X,
 Y: Integer);
var
 LastPoint: TPoint;
begin
 stX.Caption := IntToStr(X);
 stY.Caption := IntToStr(Y);
 if not FDrawing then exit;
 if FCurveIndex < 0 then exit;
 with pbCurve.Canvas do
 begin
   LastPoint := FCurves.LastPoint[FCurveIndex];
   moveTo(LastPoint.X, LastPoint.Y);
   Pen.Mode := pmXor;
   LineTo(FLastX, FLastY);
   moveTo(LastPoint.X, LastPoint.Y);
   LineTo(X, Y);
   FLastX := X;
   FLastY := Y;
 end;
end;

procedure TForm2.Shape1MouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
 if FCurveIndex < 0 then exit;
 FCurves.Color[FCurveIndex] := (Sender as TShape).Brush.Color;
end;

procedure TForm2.SpeedButton1Click(Sender: TObject);
begin
 pbCurve.Cursor := crCross;
 FDrawing := True;
end;

procedure TForm2.pbCurvePaint(Sender: TObject);
begin
 RepaintCurve;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
 FCurveIndex := -1;
 FCurves := TCurves.Create;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
 FCurves.Free;
end;

function TForm2.GetCurveIndex: integer;
begin
 Result := FCurveIndex;
end;

procedure TForm2.SetCurveIndex(const Value: integer);
begin
 FCurveIndex := Value;
end;

procedure TForm2.SpeedButton2Click(Sender: TObject);
begin
 FDrawing := false;
 FCurveIndex := -1;
 ShowCurves;
end;

procedure TForm2.pbCurveMouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
var
 Point: TPoint;
begin
 if not FDrawing then exit;
 Point.X := X;
 Point.Y := Y;
 if FCurveIndex >= 0 then
 begin
   FCurves.AddPoint(FCurveIndex, Point);
   RepaintCurve;
 end
 else
 begin
   FCurveIndex := FCurves.NewCurve;
   FLastX := X;
   FLastY := Y;
   FCurves.AddPoint(FCurveIndex, Point);
 end;
end;

procedure TForm2.ShowCurves;
var
 CurveIndex, i: integer;
 CurveString: string;
 CurveArray: TCurveArray;
begin
 memPoints.Lines.Clear;
 for CurveIndex := 0 to FCurves.Count - 1 do
 with memPoints.Lines do
 begin
   CurveString := "";
   CurveArray := FCurves.PointArray(CurveIndex);
   for i := Low(CurveArray) to High(CurveArray) do
     CurveString := CurveString + "(" + IntToStr(CurveArray[i].X) + ", " +
                          IntToStr(CurveArray[i].Y) + ") ";
   memPoints.Lines.Add(CurveString);
   CurveArray := nil;
 end;
end;

end.


 
Romkin ©   (2004-02-03 18:22) [8]

Изображение я сразу загрузил, в дизайне, но dfm не помещается, так что без него :))) на OnShow строки надо выполнять после его загрузки, как раз все устанавливается. Думаю, вопросов, как грузить, не будет?

object Form2: TForm2
 Left = 330
 Top = 191
 Width = 540
 Height = 469
 Caption = "Form2"
 Color = clBtnFace
 Font.Charset = DEFAULT_CHARSET
 Font.Color = clWindowText
 Font.Height = -11
 Font.Name = "MS Sans Serif"
 Font.Style = []
 OldCreateOrder = False
 OnCreate = FormCreate
 OnDestroy = FormDestroy
 OnShow = FormShow
 DesignSize = (
   532
   442)
 PixelsPerInch = 96
 TextHeight = 13
 object SpeedButton1: TSpeedButton
   Left = 476
   Top = 16
   Width = 23
   Height = 22
   Caption = "X"
   OnClick = SpeedButton1Click
 end
 object SpeedButton2: TSpeedButton
   Left = 476
   Top = 44
   Width = 23
   Height = 22
   Caption = "end"
   OnClick = SpeedButton2Click
 end
 object Shape1: TShape
   Left = 468
   Top = 80
   Width = 50
   Height = 25
   Brush.Color = clRed
   OnMouseUp = Shape1MouseUp
 end
 object Shape2: TShape
   Left = 468
   Top = 112
   Width = 50
   Height = 25
   Brush.Color = clBlue
   OnMouseUp = Shape1MouseUp
 end
 object Shape3: TShape
   Left = 468
   Top = 144
   Width = 50
   Height = 25
   Brush.Color = clGreen
   OnMouseUp = Shape1MouseUp
 end
 object Label1: TLabel
   Left = 8
   Top = 276
   Width = 10
   Height = 13
   Anchors = [akLeft, akBottom]
   Caption = "X:"
 end
 object Label2: TLabel
   Left = 60
   Top = 276
   Width = 10
   Height = 13
   Anchors = [akLeft, akBottom]
   Caption = "Y:"
 end
 object sbImg: TScrollBox
   Left = 4
   Top = 4
   Width = 448
   Height = 268
   Anchors = [akLeft, akTop, akRight, akBottom]
   TabOrder = 0
   object img: TImage
     Left = 0
     Top = -4
     Width = 450
     Height = 314
     AutoSize = True
   end
   object pbCurve: TPaintBox
     Left = 0
     Top = 66
     Width = 105
     Height = 105
     OnMouseMove = pbCurveMouseMove
     OnMouseUp = pbCurveMouseUp
     OnPaint = pbCurvePaint
   end
 end
 object stX: TStaticText
   Left = 20
   Top = 276
   Width = 7
   Height = 17
   Anchors = [akLeft, akBottom]
   BorderStyle = sbsSunken
   Caption = " "
   TabOrder = 1
 end
 object stY: TStaticText
   Left = 72
   Top = 276
   Width = 7
   Height = 17
   Anchors = [akLeft, akBottom]
   BorderStyle = sbsSunken
   Caption = " "
   TabOrder = 2
 end
 object memPoints: TMemo
   Left = 4
   Top = 296
   Width = 521
   Height = 129
   Anchors = [akLeft, akTop, akRight, akBottom]
   ScrollBars = ssBoth
   TabOrder = 3
   WordWrap = False
 end
end


 
Romkin ©   (2004-02-03 18:22) [9]

Вот, собственно, и весь третий пункт...


 
Галинка ©   (2004-02-04 07:17) [10]

ОГРОМНОЕ СПАСИБО

Пойду разбираться со всем, что вы мне прислали.



Страницы: 1 вся ветка

Форум: "Media";
Текущий архив: 2004.05.02;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.049 c
1-1082105019
тихий вовочка
2004-04-16 12:43
2004.05.02
Глупый вопрос об обработке сообщений


6-1078467416
IGORYOK
2004-03-05 09:16
2004.05.02
Скопировать с одного сервера на другой


8-1074764725
Yasik
2004-01-22 12:45
2004.05.02
Конвертация


7-1078480939
User_OKA
2004-03-05 13:02
2004.05.02
Разделитель


1-1082306540
Just_
2004-04-18 20:42
2004.05.02
Поиск и замена по правилу





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский