📄 mesh_motion_estimation.c
字号:
/* * * QccPack: Quantization, compression, and coding libraries * Copyright (C) 1997-2007 James E. Fowler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, * MA 02139, USA. * */#include "libQccPack.h"int QccVIDMeshMotionEstimationWarpMesh(const QccRegularMesh *reference_mesh, QccRegularMesh *current_mesh, const QccIMGImageComponent *motion_vectors_horizontal, const QccIMGImageComponent *motion_vectors_vertical){ int row, col; if (reference_mesh == NULL) return(0); if (current_mesh == NULL) return(0); if (motion_vectors_horizontal == NULL) return(0); if (motion_vectors_vertical == NULL) return(0); if (reference_mesh->vertices == NULL) return(0); if (current_mesh->vertices == NULL) return(0); if (motion_vectors_horizontal->image == NULL) return(0); if (motion_vectors_vertical->image == NULL) return(0); if ((motion_vectors_horizontal->num_rows != current_mesh->num_rows) || (motion_vectors_horizontal->num_cols != current_mesh->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationWarpMesh): Motion-vector field is inconsistent with mesh size"); return(1); } if ((motion_vectors_vertical->num_rows != current_mesh->num_rows) || (motion_vectors_vertical->num_cols != current_mesh->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationWarpMesh): Motion-vector field is inconsistent with mesh size"); return(1); } if ((current_mesh->num_rows != reference_mesh->num_rows) || (current_mesh->num_cols != reference_mesh->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Reference mesh and current mesh are not the same size"); return(1); } for (row = 0; row < current_mesh->num_rows; row++) for (col = 0; col < current_mesh->num_cols; col++) { current_mesh->vertices[row][col].x = reference_mesh->vertices[row][col].x + motion_vectors_horizontal->image[row][col]; current_mesh->vertices[row][col].y = reference_mesh->vertices[row][col].y + motion_vectors_vertical->image[row][col]; } return(0);}static int QccVIDMeshMotionEstimationCreateKernel(QccMatrix search_kernel, int block_size){ int row, col; int offset; double d; offset = block_size / 2; for (row = 0; row < block_size; row++) for (col = 0; col < block_size; col++) { d = (row - offset) * (row - offset) + (col - offset) * (col - offset); search_kernel[row][col] = exp(-d / block_size / block_size); } return(0);}static int QccVIDMeshMotionEstimationWindowSearch(QccMatrix current_block, QccMatrix reference_block, int block_size, const QccIMGImageComponent *current_frame, QccPoint *search_point, double window_size, double search_step, QccMatrix search_kernel, int subpixel_accuracy, double *motion_vector_horizontal, double *motion_vector_vertical){ double u, v; QccPoint current_point; double current_mae; double min_mae = MAXDOUBLE; for (v = -window_size; v <= window_size; v += search_step) for (u = -window_size; u <= window_size; u += search_step) { current_point.x = search_point->x + u; current_point.y = search_point->y + v; if (QccVIDMotionEstimationExtractBlock(current_frame, current_point.y, current_point.x, current_block, block_size, subpixel_accuracy)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationWindowSearch): Error calling QccVIDMotionEstimationExtractBlock()"); return(1); } current_mae = QccVIDMotionEstimationMAE(current_block, reference_block, search_kernel, block_size); if (current_mae < min_mae) { min_mae = current_mae; *motion_vector_horizontal = u; *motion_vector_vertical = v; } } return(0);}int QccVIDMeshMotionEstimationSearch(const QccIMGImageComponent *current_frame, QccRegularMesh *current_mesh, const QccIMGImageComponent *reference_frame, const QccRegularMesh *reference_mesh, QccIMGImageComponent *motion_vectors_horizontal, QccIMGImageComponent *motion_vectors_vertical, int block_size, int window_size, int subpixel_accuracy, int constrained_boundary, int exponential_kernel){ int return_value; double final_search_step; int row, col; QccPoint reference_point; double current_search_step; QccPoint search_point; QccMatrix current_block = NULL; QccMatrix reference_block = NULL; double current_window_size; double u = 0; double v = 0; QccMatrix search_kernel = NULL; int start_row, end_row; int start_col, end_col; if (current_frame == NULL) return(0); if (current_mesh == NULL) return(0); if (reference_frame == NULL) return(0); if (reference_mesh == NULL) return(0); if (motion_vectors_horizontal == NULL) return(0); if (motion_vectors_vertical == NULL) return(0); if (current_frame->image == NULL) return(0); if (current_mesh->vertices == NULL) return(0); if (reference_frame->image == NULL) return(0); if (reference_mesh->vertices == NULL) return(0); if (motion_vectors_horizontal->image == NULL) return(0); if (motion_vectors_vertical->image == NULL) return(0); if ((motion_vectors_horizontal->num_rows != reference_mesh->num_rows) || (motion_vectors_horizontal->num_cols != reference_mesh->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Motion-vector field is inconsistent with mesh size"); goto Error; } if ((motion_vectors_vertical->num_rows != reference_mesh->num_rows) || (motion_vectors_vertical->num_cols != reference_mesh->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Motion-vector field is inconsistent with mesh size"); goto Error; } if ((current_mesh->num_rows != reference_mesh->num_rows) || (current_mesh->num_cols != reference_mesh->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Reference mesh and current mesh are not the same size"); goto Error; } if ((reference_frame->num_rows != current_frame->num_rows) || (reference_frame->num_cols != current_frame->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Reference-frame size is inconsistent with current-frame size"); goto Error; } switch (subpixel_accuracy) { case QCCVID_ME_FULLPIXEL: final_search_step = 1.0; break; case QCCVID_ME_HALFPIXEL: final_search_step = 0.5; break; case QCCVID_ME_QUARTERPIXEL: final_search_step = 0.25; break; case QCCVID_ME_EIGHTHPIXEL: final_search_step = 0.125; break; default: QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Unrecognized motion-estimation accuracy (%d)", subpixel_accuracy); goto Error; } if ((current_block = QccMatrixAlloc(block_size, block_size)) == NULL) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Error calling QccMatrixAlloc()"); goto Error; } if ((reference_block = QccMatrixAlloc(block_size, block_size)) == NULL) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Error calling QccMatrixAlloc()"); goto Error; } if (exponential_kernel) { if ((search_kernel = QccMatrixAlloc(block_size, block_size)) == NULL) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Error calling QccMatrixAlloc()"); goto Error; } if (QccVIDMeshMotionEstimationCreateKernel(search_kernel, block_size)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Error calling QccVIDMeshMotionEstimationCreateKernel()"); goto Error; } } for (row = 0; row < current_mesh->num_rows; row++) for (col = 0; col < current_mesh->num_cols; col++) motion_vectors_horizontal->image[row][col] = motion_vectors_vertical->image[row][col] = 0.0; start_row = 0; end_row = current_mesh->num_rows - 1; start_col = 0; end_col = current_mesh->num_cols - 1; if (constrained_boundary)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -