📄 mesh_motion_estimation.c
字号:
{ start_row++; end_row--; start_col++; end_col--; } for (row = start_row; row <= end_row; row++) for (col = start_col; col <= end_col; col++) { reference_point.x = reference_mesh->vertices[row][col].x - (block_size / 2); reference_point.y = reference_mesh->vertices[row][col].y - (block_size / 2); if (QccVIDMotionEstimationExtractBlock(reference_frame, reference_point.y, reference_point.x, reference_block, block_size, subpixel_accuracy)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Error calling QccVIDMotionEstimationExtractBlock()"); goto Error; } for (current_search_step = 1.0; current_search_step >= final_search_step; current_search_step /= 2) { search_point.x = reference_point.x + motion_vectors_horizontal->image[row][col]; search_point.y = reference_point.y + motion_vectors_vertical->image[row][col]; current_window_size = (current_search_step == 1.0) ? (double)window_size : current_search_step; if (QccVIDMeshMotionEstimationWindowSearch(current_block, reference_block, block_size, current_frame, &search_point, current_window_size, current_search_step, search_kernel, subpixel_accuracy, &u, &v)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Error calling QccVIDMeshMotionEstimationWindowSearch()"); goto Error; } motion_vectors_horizontal->image[row][col] += u; motion_vectors_vertical->image[row][col] += v; } } if (QccVIDMeshMotionEstimationWarpMesh(reference_mesh, current_mesh, motion_vectors_horizontal, motion_vectors_vertical)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationSearch): Error calling QccVVIDMeshMotionEstimationWarpMesh()"); goto Error; } return_value = 0; goto Return; Error: return_value = 1; Return: QccMatrixFree(current_block, block_size); QccMatrixFree(reference_block, block_size); QccMatrixFree(search_kernel, block_size); return(return_value);}static int QccVIDMeshMotionEstimationExtractSubpixel(const QccIMGImageComponent *reference_frame, const QccPoint *reference_point, int subpixel_accuracy, double *subpixel_value){ QccPoint reference_point2; double scale; switch (subpixel_accuracy) { case QCCVID_ME_FULLPIXEL: scale = 1.0; break; case QCCVID_ME_HALFPIXEL: scale = 2.0; break; case QCCVID_ME_QUARTERPIXEL: scale = 4.0; break; case QCCVID_ME_EIGHTHPIXEL: scale = 8.0; break; default: QccErrorAddMessage("(QccVIDMeshMotionEstimationExtractSubpixel): Unrecognized subpixel accuracy (%d)", subpixel_accuracy); return(1); } reference_point2.x = scale * reference_point->x; reference_point2.y = scale * reference_point->y; if (QccIMGImageComponentExtractSubpixel(reference_frame, reference_point2.x, reference_point2.y, subpixel_value)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationExtractSubpixel): Error calling QccIMGImageComponentExtractSubpixel()"); return(1); } return(0);}int QccVIDMeshMotionEstimationCreateCompensatedFrame(QccIMGImageComponent *motion_compensated_frame, const QccRegularMesh *current_mesh, const QccIMGImageComponent *reference_frame, const QccRegularMesh *reference_mesh, int subpixel_accuracy){ int return_value; int row, col; int num_triangles; int triangle; QccTriangle *current_triangles = NULL; QccTriangle *reference_triangles = NULL; QccMatrix *transforms = NULL; QccPoint current_point; QccPoint reference_point; double subpixel_value; if (motion_compensated_frame == NULL) return(0); if (reference_frame == NULL) return(0); if (current_mesh == NULL) return(0); if (reference_mesh == NULL) return(0); if (motion_compensated_frame->image == NULL) return(0); if (reference_frame->image == NULL) return(0); if (current_mesh->vertices == NULL) return(0); if (reference_mesh->vertices == NULL) return(0); num_triangles = QccRegularMeshNumTriangles(current_mesh); switch (subpixel_accuracy) { case QCCVID_ME_FULLPIXEL: if ((reference_frame->num_rows != motion_compensated_frame->num_rows) || (reference_frame->num_cols != motion_compensated_frame->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Reference-frame size is inconsistent with current-frame size for full-pixel motion estimation"); goto Error; } break; case QCCVID_ME_HALFPIXEL: if ((reference_frame->num_rows != 2 * motion_compensated_frame->num_rows) || (reference_frame->num_cols != 2 * motion_compensated_frame->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Reference-frame size is inconsistent with current-frame size for half-pixel motion estimation"); goto Error; } break; case QCCVID_ME_QUARTERPIXEL: if ((reference_frame->num_rows != 4 * motion_compensated_frame->num_rows) || (reference_frame->num_cols != 4 * motion_compensated_frame->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Reference-frame size is inconsistent with current-frame size for quarter-pixel motion estimation"); goto Error; } break; case QCCVID_ME_EIGHTHPIXEL: if ((reference_frame->num_rows != 8 * motion_compensated_frame->num_rows) || (reference_frame->num_cols != 8 * motion_compensated_frame->num_cols)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Reference-frame size is inconsistent with current-frame size for eighth-pixel motion estimation"); goto Error; } break; default: QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Unrecognized motion-estimation accuracy (%d)", subpixel_accuracy); goto Error; } if ((current_triangles = (QccTriangle *)malloc(sizeof(QccTriangle) * num_triangles)) == NULL) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Error allocating memory"); goto Error; } if ((reference_triangles = (QccTriangle *)malloc(sizeof(QccTriangle) * num_triangles)) == NULL) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Error allocating memory"); goto Error; } if ((transforms = (QccMatrix *)malloc(sizeof(QccMatrix) * num_triangles)) == NULL) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Error allocating memory"); goto Error; } if (QccRegularMeshToTriangles(current_mesh, current_triangles)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Error calling QccRegularMeshToTriangles()"); goto Error; } if (QccRegularMeshToTriangles(reference_mesh, reference_triangles)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Error calling QccRegularMeshToTriangles()"); goto Error; } for (triangle = 0; triangle < num_triangles; triangle++) { if ((transforms[triangle] = QccMatrixAlloc(2, 3)) == NULL) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Error calling QccMatrixAlloc()"); goto Error; } if (QccTriangleCreateAffineTransform(¤t_triangles[triangle], &reference_triangles[triangle], transforms[triangle])) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Error calling QccTriangleCreateAffineTransform()"); goto Error; } } for (row = 0; row < motion_compensated_frame->num_rows; row++) for (col = 0; col < motion_compensated_frame->num_cols; col++) { current_point.x = (double)col; current_point.y = (double)row; for (triangle = 0; triangle < num_triangles; triangle++) if (QccTrianglePointInside(¤t_triangles[triangle], ¤t_point)) break; if (triangle >= num_triangles) QccPointCopy(&reference_point, ¤t_point); else QccPointAffineTransform(¤t_point, &reference_point, transforms[triangle]); if (QccVIDMeshMotionEstimationExtractSubpixel(reference_frame, &reference_point, subpixel_accuracy, &subpixel_value)) { QccErrorAddMessage("(QccVIDMeshMotionEstimationCreateCompensatedFrame): Error calling QccVIDMeshMotionEstimationExtractSubpixel()"); goto Error; } motion_compensated_frame->image[row][col] = subpixel_value; } return_value = 0; goto Return; Error: return_value = 1; Return: QccFree(current_triangles); QccFree(reference_triangles); if (transforms != NULL) { for (triangle = 0; triangle < num_triangles; triangle++) QccMatrixFree(transforms[triangle], 2); QccFree(transforms); } return(return_value);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -