{"id":21766356,"url":"https://github.com/drilonaliu/parallel-image-edge-detection","last_synced_at":"2026-05-17T00:08:25.488Z","repository":{"id":255185992,"uuid":"848769351","full_name":"drilonaliu/Parallel-Image-Edge-Detection","owner":"drilonaliu","description":null,"archived":false,"fork":false,"pushed_at":"2024-08-29T17:15:51.000Z","size":5054,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-30T20:03:26.314Z","etag":null,"topics":["cuda","edge-detection","gpu","image-processing"],"latest_commit_sha":null,"homepage":"","language":"Cuda","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/drilonaliu.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":"2024-08-28T11:27:29.000Z","updated_at":"2024-10-10T22:02:20.000Z","dependencies_parsed_at":"2024-08-28T13:51:36.761Z","dependency_job_id":"9545498c-2f38-43af-8086-e05247454575","html_url":"https://github.com/drilonaliu/Parallel-Image-Edge-Detection","commit_stats":null,"previous_names":["drilonaliu/parallel-image-edge-detection"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/drilonaliu/Parallel-Image-Edge-Detection","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Image-Edge-Detection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Image-Edge-Detection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Image-Edge-Detection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Image-Edge-Detection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drilonaliu","download_url":"https://codeload.github.com/drilonaliu/Parallel-Image-Edge-Detection/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drilonaliu%2FParallel-Image-Edge-Detection/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279002012,"owners_count":26083258,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["cuda","edge-detection","gpu","image-processing"],"created_at":"2024-11-26T13:16:55.678Z","updated_at":"2025-10-09T20:03:58.485Z","avatar_url":"https://github.com/drilonaliu.png","language":"Cuda","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Image Edge Detection \n\nSobel Operator is used for image edge detection. In the sequential version, we iterate on each pixel, whereas on the parallel version each thread corresponds to one pixel on the image. For every pixel, we get calculate the weighted sums $G_x$ and $G_y$, after applying the filters $S_x$ and $S_y$ respectfully, on the neighborhoud of a pixel $(x,y)$. The new pixel will be the norm of the vector $(Gx,Gy)$.\n\n$$\nS_x = \\begin{bmatrix}\n-1 \u0026 0 \u0026 1 \\\\\n-2 \u0026 0 \u0026 2 \\\\\n-1 \u0026 0 \u0026 1\n\\end{bmatrix} \\qquad\nS_y = \\begin{bmatrix}\n-1 \u0026 -2 \u0026 1 \\\\\n 0 \u0026 0 \u0026 0 \\\\\n 1 \u0026 2 \u0026 1\n\\end{bmatrix}\n$$\n\nFor every pixel $(x,y)$ of the image $f(x,y)$  we calculate:\n\n$$ G_x = \\sum_{s=-1}^{1} \\sum_{t=-1}^{1} S_x(s+1,t+1)*f(x+s,y+t) $$ \n\n$$ G_y = \\sum_{s=-1}^{1} \\sum_{t=-1}^{1} S_y(s+1,t+1)*f(x+s,y+t) $$ \n\nThe new pixel at $(x,y)$ of the new image $g(x,y)$ is the Euclidian norm:\n\n$$ g(x,y) = \\lVert (G_x,G_y) \\rVert = \\sqrt{G_x^2 + G_y^2} $$\n\nThe kernel that does this is given below:\n\n```\n\t__global__ void cudaFindImageEdges(uchar* image, uchar* edgedImage, int imageCols, int imageRows) {\n\t\tint i = blockIdx.x;\n\t\tint j = blockIdx.y;\n\n\t\tint thread_index = threadIdx.x + blockDim.x * blockIdx.x;\n\n\t\t//Dont let any thread larger than image size enter the kernel\n\t\tif (thread_index \u003c imageCols * imageRows) {\n\t\t\tint i = thread_index % imageRows; //column\n\t\t\tint j = thread_index / imageCols; //row\n\t\t\t//Dont work on edges of images\n\t\t\tif (i \u003e 0 \u0026\u0026 j \u003e 0 \u0026\u0026 i \u003c imageCols \u0026\u0026 j \u003c imageRows) {\n\n\t\t\t\tint gX = 0;\n\t\t\t\tint gY = 0;\n\n\t\t\t\t//Grab the neighbourhood\n\t\t\t\tfor (int row = -1; row \u003c= 1; row++) {\n\t\t\t\t\tfor (int col = -1; col \u003c= 1; col++) {\n\t\t\t\t\t\tgX += image[i + row + imageCols * (j + col)] * Sx[row + 1][col + 1];;\n\t\t\t\t\t\tgY += image[i + row + imageCols * (j + col)] * Sy[row + 1][col + 1];;\n\n\t\t\t\t\t\t//pixel(i,y) = image[i+cols*y]\n\t\t\t\t\t\n\t\t\t\t\t\t//This is how we calculated gX and gY in c++ only.\n\t\t\t\t\t\t/*\tgX += img.at\u003cuchar\u003e(i + row, j + col) * Sx[row + 1][col + 1];\n\t\t\t\t\t\t\tgY += img.at\u003cuchar\u003e(i + row, j + col) * Sy[row + 1][col + 1];;*/\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdouble s = sqrt((float)(gX * gX + gY * gY));\n\t\t\t\tedgedImage[thread_index] = s;\n\t\t\t}\n\t\t\telse {\n\t\t\t\t//Edges of the image are just copied to the new image\n\t\t\t\tedgedImage[thread_index] = image[thread_index];\n\t\t\t}\n\t\t}\n\t}\n```\n\nIf we apply the sobel operator on the original Lena image, we will get the image with calculated edges as below:\n\n\u003cdiv\u003e\n \u003cimg src = \"readMeImages/lena.jpg\"\u003e\n  \u003cimg src = \"readMeImages/lena_edges.jpg\"\u003e\n\u003c/div\u003e\n\n## open cv \nYou can extract the open cv installer in the Common folder, and you won't be needing to import the libraries manually. Install open cv here: https://opencv.org/get-started/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrilonaliu%2Fparallel-image-edge-detection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrilonaliu%2Fparallel-image-edge-detection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrilonaliu%2Fparallel-image-edge-detection/lists"}