Книга программиста/Фильтрация изображений на PascalABC.Net

К оглавлению | Назад | Вперёд

Все программы, код которых выложен здесь, являются работоспособными. На момент написания программ использовалась среда PascalABC.Net 3.0.

Комментарии к программамПравить

  1. FilterMatrix - матрица, которая позволяет по разному обрабатывать изображение.
  2. Pic2 - результирующее изображение.

Изменение яркостиПравить

Формулы
r = Round(c.R + 128 * N / 100)
g = Round(c.G + 128 * N / 100)
b = Round(c.B + 128 * N / 100)
uses GraphABC; 
const
  N = -50;

var
  Pic1: Picture;
  V: real := 128 * N / 100;

procedure TruncColor(var a: integer);
begin
  if a > 255 then a := 255 else
  if a < 0 then a := 0; 
end;

begin
  Pic1 := new Picture('C:\Asya\pine-nuts.jpg'); 
  
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 0 to Pic1.Width - 1 do 
    for var j := 0 to Pic1.Height - 1 do
    begin
      var c := Pic1.GetPixel(i, j);
      var r := Round(c.R + V); 
      var g := Round(c.G + V); 
      var b := Round(c.B + V); 
      
      TruncColor(r); 
      TruncColor(g); 
      TruncColor(b); 
      
      Pic1.PutPixel(i, j, RGB(r, g, b));
    end;
  
  Pic1.Draw(0, 0);
end.

Инвертирование изображенияПравить

Стандартный вариантПравить

Формулы
r = 255 - c.R
g = 255 - c.G
b = 255 - c.B
uses GraphABC; 
var
  Pic1: Picture;

begin
  Pic1 := new Picture('C:\asya\pine-nuts.jpg'); 
  
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 0 to Pic1.Width - 1 do 
    for var j := 0 to Pic1.Height - 1 do
    begin
      var c := Pic1.GetPixel(i, j);
      Pic1.PutPixel(i, j, RGB(255 - c.R, 255 - c.G, 255 - c.B));
    end;
  
  Pic1.Draw(0, 0);
end.

Усложненный вариантПравить

uses GraphABC;
const
  FactorA = 100;
  FactorR = 10;
  FactorG = 0;
  FactorB = 40;

var
  Pic1: Picture;

//Выполняет интерполяцию между числовыми значениями.
function ByteInterpolation(a, b, p: byte) := Round(a + (b - a) * p / 100);

//Выполняет интерполяцию цвета.
function InterpolateColor(с1, с2: Color; pA, pR, pG, pB: byte) := ARGB(ByteInterpolation(с1.A, с2.A, pA), ByteInterpolation(с1.R, с2.R, pR), ByteInterpolation(с1.G, с2.G, pG), ByteInterpolation(с1.B, с2.B, pB));

begin
  Pic1 := new Picture('C:\Ilya\pine-nuts.jpg'); 
  
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 0 to Pic1.Width - 1 do 
    for var j := 0 to Pic1.Height - 1 do
    begin
      var с := Pic1.GetPixel(i, j);
      var r := 255 - с.R;
      var g := 255 - с.G;
      var b := 255 - с.B;
      
      Pic1.PutPixel(i, j, InterpolateColor(с, RGB(r, g, b), FactorA, FactorR, FactorG, FactorB));
    end;
  
  Pic1.Draw(0, 0);
end.

P. S. Для интерполяции между числами можно так же использовать:

function Interpolation(a, b, p: integer) := Round(a + (b - a) * p / 100);

ОконтуриваниеПравить

900px

uses GraphABC; 
var
  Pic1, Pic2: Picture; 
  FilterMatrix: array [0..2, 0..2] of real; 
  S: real; 
  R, G, B: real;

procedure TruncColor(var a: integer);
begin
  if a > 255 then a := 255 else
  if a < 0 then a := 0; 
end;

begin
  Pic1 := new Picture('C:\Ilya\MjcVeXIf.jpg');
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  Pic2 := new Picture(Pic1.Width, Pic1.Height);
  for var i := 1 to Pic1.Width - 2 do 
    for var j := 1 to Pic1.Height - 2 do 
      Pic2.PutPixel(i, j, Pic1.GetPixel(i, j));
  
  FilterMatrix[0, 0] := 1;FilterMatrix[0, 1] := 0;FilterMatrix[0, 2] := 1; 
  FilterMatrix[1, 0] := 0;FilterMatrix[1, 1] := -4;FilterMatrix[1, 2] := 0; 
  FilterMatrix[2, 0] := 1;FilterMatrix[2, 1] := 0;FilterMatrix[2, 2] := 1; 
  
  LockDrawing(); 
  for var i := 1 to Pic1.Width - 2 do 
    for var j := 1 to Pic1.Height - 2 do 
    begin
      for var i2 := i - 1 to i + 1 do 
        for var j2 := j - 1 to j + 1 do 
        begin
          var m := FilterMatrix[i2 - (i - 1), j2 - (j - 1)];
          var c := Pic1.GetPixel(i2, j2);
          R := R + c.R * m; 
          G := G + c.G * m; 
          B := B + c.B * m; 
          S := S + m; 
        end; 
      if S = 0 then S := 1; 
      var rR := Round(R / S); 
      var rG := Round(G / S); 
      var rB := Round(B / S); 
      
      TruncColor(rR); 
      TruncColor(rG); 
      TruncColor(rB); 
      
      Pic2.PutPixel(i, j, RGB(rR, rG, rB)); 
      
      R := 0; 
      G := 0; 
      B := 0; 
      S := 0; 
    end; 
  
  Pic2.Draw();
  Redraw(); 
end.

Преобразование в нецветное изображениеПравить

Формулы
r = Round((c.R + c.G + c.B) / 3)
g = Round((c.R + c.G + c.B) / 3)
b = Round((c.R + c.G + c.B) / 3)
uses GraphABC; 
var
  Pic1: Picture;

begin
  Pic1 := new Picture('C:\Ilya\pine-nuts.jpg'); 
  
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 0 to Pic1.Width - 1 do 
    for var j := 0 to Pic1.Height - 1 do
    begin
      var c := Pic1.GetPixel(i, j);
      var cRGB := Round((c.R + c.G + c.B) / 3);
      Pic1.PutPixel(i, j, RGB(cRGB, cRGB, cRGB));
    end;
  
  Pic1.Draw(0, 0);
end.

РазмытиеПравить

900px

uses GraphABC; 
var
  Pic1, Pic2: Picture; 
  FilterMatrix: array [0..2, 0..2] of real; 
  S: real; 
  R, G, B: real;

procedure TruncColor(var a: integer);
begin
  if a > 255 then a := 255 else
  if a < 0 then a := 0; 
end;

begin
  Pic1 := new Picture('C:\Ilya\MjcVeXIf.jpg');
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  Pic2 := new Picture(Pic1.Width, Pic1.Height);
  for var i := 1 to Pic1.Width - 2 do 
    for var j := 1 to Pic1.Height - 2 do 
      Pic2.PutPixel(i, j, Pic1.GetPixel(i, j));
  
  FilterMatrix[0, 0] := 1; FilterMatrix[0, 1] := 1; FilterMatrix[0, 2] := 1; 
  FilterMatrix[1, 0] := 1; FilterMatrix[1, 1] := 1; FilterMatrix[1, 2] := 1; 
  FilterMatrix[2, 0] := 1; FilterMatrix[2, 1] := 1; FilterMatrix[2, 2] := 1; 
  
  LockDrawing(); 
  for var i := 1 to Pic1.Width - 2 do 
    for var j := 1 to Pic1.Height - 2 do 
    begin
      for var i2 := i - 1 to i + 1 do 
        for var j2 := j - 1 to j + 1 do 
        begin
          var m := FilterMatrix[i2 - (i - 1), j2 - (j - 1)];
          var c := Pic1.GetPixel(i2, j2);
          R := R + c.R * m; 
          G := G + c.G * m; 
          B := B + c.B * m; 
          S := S + m; 
        end; 
      if S = 0 then S := 1; 
      var rR := Round(R / S); 
      var rG := Round(G / S); 
      var rB := Round(B / S); 
      
      TruncColor(rR); 
      TruncColor(rG); 
      TruncColor(rB); 
      
      Pic2.PutPixel(i, j, RGB(rR, rG, rB)); 
      
      R := 0; 
      G := 0; 
      B := 0; 
      S := 0; 
    end; 
  
  Pic2.Draw();
  Redraw(); 
end.

СепияПравить

900px

uses GraphABC; 
const
  R = 85;
  G = 50;
  B = 0;
  Intensivity = 40;

var
  Pic1: Picture;

function ByteInterpolation(a, b, p: byte) := Round(a + (b - a) * p / 100);

function InterpolateColor(с1, с2: Color; p: byte) := ARGB(ByteInterpolation(с1.A, с2.A, p), ByteInterpolation(с1.R, с2.R, p), ByteInterpolation(с1.G, с2.G, p), ByteInterpolation(с1.B, с2.B, p));

begin
  Pic1 := new Picture('C:\Ilya\MjcVeXIf.jpg'); 
  
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 0 to Pic1.Width - 1 do 
    for var j := 0 to Pic1.Height - 1 do
    begin
      var c := Pic1.GetPixel(i, j);
      var gray := Round((c.R + c.G + c.B) / 3);
      Pic1.PutPixel(i, j, InterpolateColor(RGB(gray, gray, gray), RGB(R, G, B), Intensivity));
    end;
  
  Pic1.Draw(0, 0);
end.

Тонирование изображенияПравить

uses GraphABC; 
const
  R = 100;
  G = 0;
  B = 0;
  Intensivity = 50;

var
  Pic1: Picture;

function ByteInterpolation(a, b, p: byte) := Round(a + (b - a) * p / 100);

function InterpolateColor(с1, с2: Color; p: byte):= ARGB(ByteInterpolation(с1.A, с2.A, p), ByteInterpolation(с1.R, с2.R, p), ByteInterpolation(с1.G, с2.G, p), ByteInterpolation(с1.B, с2.B, p));

begin
  Pic1 := new Picture('C:\Ilya\pine-nuts.jpg'); 
  
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 0 to Pic1.Width - 1 do 
    for var j := 0 to Pic1.Height - 1 do
    begin
      var c := Pic1.GetPixel(i, j);
      var gray := Round((c.R + c.G + c.B) / 3);
      Pic1.PutPixel(i, j, InterpolateColor(RGB(gray, gray, gray), RGB(R, G, B), Intensivity));
    end;
  
  Pic1.Draw(0, 0);
end.

Изменение контрастаПравить

Увеличение контрастаПравить

900px

Формулы
r = Round((c.R * 100 - 128 * N) / (100 - N))
g = Round((c.G * 100 - 128 * N) / (100 - N))
b = Round((c.B * 100 - 128 * N) / (100 - N))
uses GraphABC;
const
  N = 99;

var
  Pic1: Picture;

procedure TruncColor(var a: integer);
begin
  if a > 255 then a := 255 else
  if a < 0 then a := 0; 
end;

begin
  Pic1 := new Picture('C:\Ilya\MjcVeXIf.jpg'); 
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 1 to Pic1.Width - 1 do 
    for var j := 1 to Pic1.Height - 1 do 
    begin
      var c := Pic1.GetPixel(i, j);
      var a := 128 * N;
      var p := 100 - N;
      var r := Round((c.R * 100 - a) / p); 
      var g := Round((c.G * 100 - a) / p); 
      var b := Round((c.B * 100 - a) / p); 
      
      TruncColor(r); 
      TruncColor(g); 
      TruncColor(b); 
      
      Pic1.PutPixel(i, j, RGB(r, g, b)); 
    end; 
  
  LockDrawing();
  Pic1.Draw();
  Redraw();
end.
uses GraphABC; 
const
  N = 3.0;

var
  Pic1: Picture;
  Rm, Gm, Bm: integer;

procedure TruncColor(var a: integer);
begin
  if a > 255 then a := 255 else
  if a < 0 then a := 0; 
end;

begin
  Pic1 := new Picture('C:\Ilya\MjcVeXIf.jpg'); 
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 1 to Pic1.Width - 1 do 
    for var j := 1 to Pic1.Height - 1 do
    begin
      var c := Pic1.GetPixel(i, j);
      Inc(Rm, c.R);
      Inc(Gm, c.G);
      Inc(Bm, c.B);
    end;
  
  var S := Pic1.Width * Pic1.Height;
  Rm := Round(Rm / S);
  Gm := Round(Gm / S);
  Bm := Round(Bm / S);
  
  for var i := 1 to Pic1.Width - 1 do 
    for var j := 1 to Pic1.Height - 1 do
    begin
      var c := Pic1.GetPixel(i, j);
      var dR := Round((c.R - Rm) * N);
      var dG := Round((c.G - Gm) * N);
      var dB := Round((c.B - Bm) * N);
      
      var r := Rm + dR;
      var g := Gm + dG;
      var b := Bm + dB;
      
      TruncColor(r); 
      TruncColor(g); 
      TruncColor(b); 
      
      Pic1.PutPixel(i, j, RGB(r, g, b)); 
    end; 
  
  LockDrawing();
  Pic1.Draw();
  Redraw();
end.

Уменьшение контрастаПравить

900px

Формулы
r = Round((c.R * (100 - N) + 128 * N) / 100)
g = Round((c.G * (100 - N) + 128 * N) / 100)
b = Round((c.B * (100 - N) + 128 * N) / 100)
uses GraphABC; 
const
  N = 90;

var
  Pic1: Picture;

procedure TruncColor(var a: integer);
begin
  if a > 255 then a := 255 else
  if a < 0 then a := 0; 
end;

begin
  Pic1 := new Picture('C:\Ilya\MjcVeXIf.jpg'); 
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 1 to Pic1.Width - 1 do 
    for var j := 1 to Pic1.Height - 1 do 
    begin
      var c := Pic1.GetPixel(i, j);
      var a := 128 * N;
      var p := 100 - N;
      var r := Round((c.R * p + a) / 100); 
      var g := Round((c.G * p + a) / 100); 
      var b := Round((c.B * p + a) / 100); 
      
      TruncColor(r); 
      TruncColor(g); 
      TruncColor(b); 
      
      Pic1.PutPixel(i, j, RGB(r, g, b)); 
    end; 
  
  LockDrawing();
  Pic1.Draw();
  Redraw();
end.

Увеличение резкостиПравить

900px

uses GraphABC; 
var
  Pic1, Pic2: Picture; 
  FilterMatrix: array [0..2, 0..2] of real; 
  S: real; 
  R, G, B: real;

procedure TruncColor(var a: integer);
begin
  if a > 255 then a := 255 else
  if a < 0 then a := 0; 
end;

begin
  Pic1 := new Picture('C:\Ilya\MjcVeXIf.jpg');
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  Pic2 := new Picture(Pic1.Width, Pic1.Height);
  for var i := 1 to Pic1.Width - 2 do 
    for var j := 1 to Pic1.Height - 2 do 
      Pic2.PutPixel(i, j, Pic1.GetPixel(i, j));
  
  FilterMatrix[0, 0] := -1; FilterMatrix[0, 1] := -1; FilterMatrix[0, 2] := -1; 
  FilterMatrix[1, 0] := -1; FilterMatrix[1, 1] := 9;  FilterMatrix[1, 2] := -1; 
  FilterMatrix[2, 0] := -1; FilterMatrix[2, 1] := -1; FilterMatrix[2, 2] := -1; 
  
  LockDrawing(); 
  for var i := 1 to Pic1.Width - 2 do 
    for var j := 1 to Pic1.Height - 2 do 
    begin
      for var i2 := i - 1 to i + 1 do 
        for var j2 := j - 1 to j + 1 do 
        begin
          var m := FilterMatrix[i2 - (i - 1), j2 - (j - 1)];
          var c := Pic1.GetPixel(i2, j2);
          R := R + c.R * m; 
          G := G + c.G * m; 
          B := B + c.B * m; 
          S := S + m; 
        end; 
      if S = 0 then S := 1; 
      var rR := Round(R / S); 
      var rG := Round(G / S); 
      var rB := Round(B / S); 
      
      TruncColor(rR); 
      TruncColor(rG); 
      TruncColor(rB); 
      
      Pic2.PutPixel(i, j, RGB(rR, rG, rB)); 
      
      R := 0; 
      G := 0; 
      B := 0; 
      S := 0; 
    end; 
  
  Pic2.Draw();
  Redraw(); 
end.

Изменение цветового балансаПравить

900px

Формулы
r = Round(c.R + 128 * NR / 100)
g = Round(c.G + 128 * NG / 100)
b = Round(c.B + 128 * NB / 100)
uses GraphABC; 
const
  NR = 100; 
  NG = 1; 
  NB = 1;

var
  Pic1: Picture;

procedure TruncColor(var a: integer);
begin
  if a > 255 then a := 255 else
  if a < 0 then a := 0; 
end;

begin
  Pic1 := new Picture('C:\Ilya\MjcVeXIf.jpg'); 
  SetWindowIsFixedSize(true); 
  SetWindowSize(Pic1.Width, Pic1.Height);
  CenterWindow();
  
  for var i := 1 to Pic1.Width - 1 do 
    for var j := 1 to Pic1.Height - 1 do 
    begin
      var c := Pic1.GetPixel(i, j);
      var r := Round(c.R + 128 * NR / 100); 
      var g := Round(c.G + 128 * NG / 100); 
      var b := Round(c.B + 128 * NB / 100); 
      
      TruncColor(r); 
      TruncColor(g); 
      TruncColor(b); 
      
      Pic1.PutPixel(i, j, RGB(r, g, b)); 
    end;
  
  LockDrawing();
  Pic1.Draw();
  Redraw();
end.