{"id":17038201,"url":"https://github.com/bchao1/homography","last_synced_at":"2026-04-29T19:31:26.078Z","repository":{"id":113819564,"uuid":"286492062","full_name":"bchao1/homography","owner":"bchao1","description":"2D projection geometry with homography.","archived":false,"fork":false,"pushed_at":"2020-08-11T14:28:52.000Z","size":3634,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-29T00:26:41.022Z","etag":null,"topics":["computer-graphics","computer-vision","homography","image-processing","projection-geometry"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bchao1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-10T14:06:36.000Z","updated_at":"2026-02-08T07:02:27.000Z","dependencies_parsed_at":"2023-11-26T22:45:10.697Z","dependency_job_id":null,"html_url":"https://github.com/bchao1/homography","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bchao1/homography","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bchao1%2Fhomography","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bchao1%2Fhomography/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bchao1%2Fhomography/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bchao1%2Fhomography/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bchao1","download_url":"https://codeload.github.com/bchao1/homography/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bchao1%2Fhomography/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32440838,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T18:12:22.909Z","status":"ssl_error","status_checked_at":"2026-04-29T18:11:33.322Z","response_time":110,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["computer-graphics","computer-vision","homography","image-processing","projection-geometry"],"created_at":"2024-10-14T08:56:15.207Z","updated_at":"2026-04-29T19:31:26.063Z","avatar_url":"https://github.com/bchao1.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# homography\n\nThe meme square with projection geometry.\n\n![img](./results/res.jpg)\n\n## Usage\nThe main algorithm is in `homography/main.py`. To process the images, you need to specify custom parameters in `homography/config.yaml` file:\n- `canvas_image`: file path of the background canvas image\n- `project_images`: list of file paths of the images to project onto the canvas\n- `output_image`: file path of the output image\n- `coors`: a list of quadrilateral corners in canvas coordinates. Should be same length as `project_images`. Note that in the config file, `x` is defined as the vertical axis, while `y` is the horizontal axis.\n\n```\nThis pixel is (x, y) = (5, 2).\n __ __ __ __ __ __ __ y (width)\n|__|__|__|__|__|__   \n|__|__|__|__|__|__   \n|__|__|__|__|__|__   \n|__|__|__|__|__|__   \n|__|██|__|__|__|__\n|__|__|__|__|__|__   \n|\nx (height)\n```\n\nReferring to `homography/config.yaml`, the four corners of image `1.jpg`, starting from top-left in clockwise order, will be projected to the first entry of `coors`, which are four canvas coordinates:\n```yaml\ncoors:\n  - top_left: \n      x: 296.3452162756598\n      y: 795.149285190616\n    top_right:\n      x: 49.88489736070392\n      y: 1194.9957844574778\n    bottom_right:\n      x: 346.23295454545456\n      y: 1197.9741568914956\n    bottom_left:\n      x: 460.90029325513194\n      y: 799.6168438416423\n```\n\nAfter modifying `config.yaml`, simply run:\n```\npython3 main.py\n```\nin `homography/`. You can also try out the demo `config.yaml` provided, using images in `data/`.\n   \n## How this works\n### Homography\nProjecting a 2D image onto another image (the \"canvas\") involves computing the tranformation between two homogeneous coordinate systems. We refer to the coordinate system of the image to project as the **source coordinates**, and the coordinate system of the canvas as the **target coordinates**.\n\n![Coordinate transforms](./images/coordinates.png)\n\nSuppose a point `(u_x, u_y, 1)` in the source coordinate is projected to a point in `(v_x, v_y, 1)` in target coordinates, we can represent the projection as a **homography** **H**, which is a 3*3 matrix.\n\n![Homography](./images/homography.png)\n\nSince H is *invariant to scaling*, we usually constrain **h_33 = 1** so that **H** has 8 degree of freedom (DoF) rather than 9. Another way to enforce 8 DoF is constraining the squared sum of all elements in **H** to be 1 (which turns out to be a more robust constraint).\n\n### Solving H\nTo solve **H**, we need 8 equations since **H** has 8 DoF. This is equivalent to 4 pairs of mappings between source and target coordinates(4 points define a homography). We can simply choose the four corners of the source image and its expected transformed target coordinates to construct our equations.\n  \nFor each homogeneous coordinate mapping `(u_x, u_y, 1) -\u003e (v_x, v_y, 1)`, we can write down two equations:\n\n![Equation 1](./images/eq1.png)\n\nWriting in matrix multiplication form:\n\n![Equation 2](./images/eq2.png)\n\nSince we have 4 pairs of coordinate mappings, we can stack all 2 * 9 matrices into a single 8 * 9 matrix **A**, and solve the homogeneous system:\n```\nAh = 0, subject to ||h|| = 1\n```\nWe solve **h** by performing [singular value decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition) on **A**\u003csup\u003eT\u003c/sup\u003e**A**. **h** would be the eigenvector corresponding to the smallest eigenvalue.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbchao1%2Fhomography","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbchao1%2Fhomography","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbchao1%2Fhomography/lists"}