【OpenCV 基础知识 15】蛇形处理算法

发布于:2024-05-24 ⋅ 阅读:(137) ⋅ 点赞:(0)

函数 cvSnakeImage 更新 snake 是为了最小化 snake 的整个能量,其中能量是依赖于轮廓形状的内部能量(轮廓越光滑,内部能量越小)以及依赖于能量场的外部能量之和,外部能量通常在哪些局部能量极值点中达到最小值(这些局部能量极值点与图像梯度表示的图像边缘相对应)。
参数 criteria.epsilon 用来定义必须从迭代中除掉以保证迭代正常运行的点的最少数目。
如果在迭代中去掉的点数目小于 criteria.epsilon 或者函数达到了最大的迭代次数 criteria.max_iter ,则终止函数。

program cv_SnakeImage;

{$APPTYPE CONSOLE}
{$POINTERMATH ON}

uses
  System.SysUtils,
  ocv.highgui_c,
  ocv.core_c,
  ocv.core.types_c,
  ocv.imgproc_c,
  ocv.imgproc.types_c,
  ocv.legacy,
  uResourcePaths;

const
  w = 500;
  filename = cResourceMedia + 'cat2.jpg';

var
  imgA, imgB, imgAA: pIplImage;
  storage: pCvMemStorage;
  contour: pCvPointArray;
  Approx_contours: PcvSeq;
  contour_num: integer;
  i1, i2, i, j, length, f1: integer;
  point: pInteger;
  c_alpha: single = 0.45;
  c_beta: single = 0.10;
  c_gamma: single = 0.45;
  contours: pCvPoint;

begin
  try
    // 创建名为 'image' 的窗口,窗口属性为自动调整大小
    cvNamedWindow('image', 1);

    // 从文件加载图像并将其分配给变量 `imgA`
    imgA := cvLoadImage(filename, CV_LOAD_IMAGE_UNCHANGED);

    // 创建与 imgA 相同大小、深度和通道数的图像,将其分配给变量 `imgAA`
    imgAA := cvCreateImage(cvSize(imgA^.width, imgA^.height), imgA^.depth, imgA^.nChannels);

    // 复制图像 imgA 到 imgAA,也可以选择进行高斯平滑处理
    // cvSmooth(imgA, imgAA, CV_GAUSSIAN, 7, 0, 0);
    cvCopy(imgA, imgAA);

    // 创建与 imgA 相同大小的单通道灰度图像,将其分配给变量 `imgB`
    imgB := cvCreateImage(cvSize(imgA^.width, imgA^.height), IPL_DEPTH_8U, 1);

    // 将彩色图像 imgAA 转换为灰度图像 imgB
    cvCvtColor(imgAA, imgB, CV_BGR2GRAY);

    // 定义曲线的长度和分配内存空间
    length := 200;
    contour := AllocMem(sizeof(TCvPoint) * length);

    // 生成具有 length 个点的圆形轮廓
    for i := 0 to length - 1 do
    begin
      contour[i].x := round(200 * cos(2 * PI * i / length) + 100);
      contour[i].y := round(200 * sin(2 * PI * i / length) + 100);
    end;

    // 进入循环,执行蛇形图像处理
    while true do
    begin
      // 使用蛇形图像处理算法更新轮廓
      cvSnakeImage(imgB, contour, length, @c_alpha, @c_beta, @c_gamma, CV_VALUE, cvSize(21, 21),
        cvTermCriteria(CV_TERMCRIT_ITER, 1, 0.0), 1);

      // 复制 imgAA 到 imgA,并在图像上绘制蛇形轮廓
      cvCopy(imgAA, imgA);
      for i := 0 to length - 2 do
        cvLine(imgA, contour[i], contour[i + 1], CV_RGB(255, 0, 0), 2, 8, 0);
      cvLine(imgA, contour[length - 1], contour[0], CV_RGB(255, 0, 0), 2, 8, 0);

      // 在 'image' 窗口中显示图像
      cvShowImage('image', imgA);

      // 等待200毫秒,如果按下ESC键(ASCII码27),则退出循环
      if cvWaitKey(200) = 27 then
        Break;
    end;

    // 释放图像资源和关闭窗口
    cvReleaseImage(imgA);
    cvReleaseImage(imgB);
    cvDestroyAllWindows;

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.