{"id":29165,"date":"2026-03-02T10:08:48","date_gmt":"2026-03-02T09:08:48","guid":{"rendered":"https:\/\/www.heliotis.com\/tutorials2\/subpixel-accuracy-in-image-processing\/"},"modified":"2026-08-16T20:01:30","modified_gmt":"2026-08-16T18:01:30","slug":"subpixel-accuracy-in-image-processing","status":"publish","type":"tutorial","link":"https:\/\/www.heliotis.com\/en\/tutorials2\/subpixel-accuracy-in-image-processing\/","title":{"rendered":"Subpixel Accuracy in Image Processing"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Why lateral dimensions can be determined much more precisely than pixel size<\/h2>\n\n<p class=\"wp-block-paragraph\"><strong>Summary<\/strong><br\/>In industrial image processing, it is often assumed: &#8220;A pixel is the smallest measurable lateral unit.&#8221; This is true for pure pixel counting\u2014but not for determining the position of edges, lines, or centers. Through subpixel evaluation, the position of an edge between pixel centers can be determined more accurately. This application note uses a real-world example to show how, despite a lateral pixel size of approx. <strong>30 \u00b5m<\/strong> x <strong>30 \u00b5m<\/strong>, a repeatability of <strong>2\u20133 \u00b5m<\/strong> is achieved (typically ~1\/10th of a pixel under suitable conditions).   <\/p>\n\n<h2 class=\"wp-block-heading\">1. Motivation<\/h2>\n\n<p class=\"wp-block-paragraph\">Many users derive the measurement limit directly from the pixel size:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Pixel size = smallest lateral measurement<\/li>\n\n\n\n<li>&#8220;Subpixel&#8221; sounds like &#8220;magic&#8221;<\/li>\n<\/ul>\n\n<p class=\"wp-block-paragraph\">The crucial point is: <strong>Edges are not imaged by optics, sensors, and lighting as a sharp step change on exactly one pixel<\/strong>, but as a transition across several pixels. It is precisely this transition profile that contains the information needed to determine a position <strong>between<\/strong> pixel centers. <\/p>\n\n<h2 class=\"wp-block-heading\">2. Basic Principle: Why subpixel is possible<\/h2>\n\n<p class=\"wp-block-paragraph\">If an edge does not run exactly through pixel centers, its intensity is distributed over several neighboring pixels. This creates a <strong>brightness gradient<\/strong> (transition profile) across multiple pixels. <\/p>\n\n<div class=\"wp-block-media-text is-stacked-on-mobile\" style=\"margin-top:0;margin-right:0;margin-bottom:0;margin-left:0;padding-top:20px;padding-right:0px;padding-bottom:40px;padding-left:0px\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/www.heliotis.com\/wp-content\/uploads\/2026\/03\/sub-pixel-concept.png\" alt=\"\" class=\"wp-image-25553 size-full\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\"><em>Figure 1: Principle of subpixel-accurate edge determination<\/em><\/p>\n<\/div><\/div>\n\n<p class=\"wp-block-paragraph\">Instead of determining the &#8220;pixel index of the step,&#8221; the edge position is estimated as a <strong>continuous parameter<\/strong>\u2014e.g., by:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Interpolation around the gradient maximum (1D\/2D)<\/li>\n\n\n\n<li>Fitting a model to the edge profile (e.g., sigmoid\/error function)<\/li>\n\n\n\n<li>Geometric fit (line\/circle) to many subpixel edge points (Least Squares)<\/li>\n<\/ul>\n\n<p class=\"wp-block-paragraph\"><strong>Important:<\/strong> Subpixel does not mean &#8220;arbitrarily accurate.&#8221; The achievable precision is limited by, among other things: <\/p>\n\n<ul class=\"wp-block-list\">\n<li>Signal-to-Noise Ratio (SNR)<\/li>\n\n\n\n<li>Bit depth \/ quantization<\/li>\n\n\n\n<li>Optics (MTF), focus, motion<\/li>\n\n\n\n<li>Contrast &amp; lighting (avoid saturation)<\/li>\n\n\n\n<li>Model\/fit bias (systematic deviations)<\/li>\n<\/ul>\n\n<p class=\"wp-block-paragraph\"><strong>Practical rule of thumb:<\/strong> Under good conditions, <strong>factors of 5\u00d7 to 10\u00d7<\/strong> compared to &#8220;pixel accuracy&#8221; are realistic.<\/p>\n\n<h2 class=\"wp-block-heading\">3. Measurement Object and Setup<\/h2>\n\n<h3 class=\"wp-block-heading\">3.1 Measurement Object<\/h3>\n\n<p class=\"wp-block-paragraph\">A PCB connector <strong>DFMC 1.5\/3-ST-3.5<\/strong> (\u00a9 Phoenix Contact) with <strong>6 round cavities<\/strong> serves as an example.<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Nominal diameter: <strong>\u00d8 3.0 mm<\/strong><\/li>\n\n\n\n<li>Tolerance: <strong>\u00b1 50 \u00b5m<\/strong> (LSL = 2.95 mm, USL = 3.05 mm)<\/li>\n<\/ul>\n\n<p class=\"wp-block-paragraph\">Goal:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Repeatability of diameter determination<\/li>\n\n\n\n<li>Demonstration of subpixel capability in practice<\/li>\n<\/ul>\n\n<h3 class=\"wp-block-heading\">3.2 Measurement System<\/h3>\n\n<ul class=\"wp-block-list\">\n<li><strong>heliInspect\u2122 H9S 0.8\u00d7<\/strong> with <strong>S40U<\/strong> sensor<\/li>\n\n\n\n<li>Lighting: <strong>Red LED<\/strong><\/li>\n\n\n\n<li>Mechanics: Mounted on <strong>heliProfiler\u2122 P4<\/strong><\/li>\n\n\n\n<li>Evaluation: Contour detection + circle fit (Least Squares \/ RLS)<\/li>\n<\/ul>\n\n<div class=\"wp-block-media-text is-stacked-on-mobile\" style=\"padding-top:20px;padding-bottom:20px;grid-template-columns:33% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/www.heliotis.com\/wp-content\/uploads\/2026\/03\/phoenix_contact.png\" alt=\"\" class=\"wp-image-25559 size-full\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\"><em>Figure 2: Measurement object (connector) and measurement setup\/view of the cavities<\/em><\/p>\n<\/div><\/div>\n\n<h2 class=\"wp-block-heading\">4. Data Acquisition and Evaluation<\/h2>\n\n<h3 class=\"wp-block-heading\">4.1 3D Data and ROI Selection<\/h3>\n\n<p class=\"wp-block-paragraph\">For contour analysis, only areas with sufficient signal are evaluated (above the noise level). The six cavities are selected as ROIs. <\/p>\n\n<div class=\"wp-block-media-text is-stacked-on-mobile\" style=\"padding-top:20px;padding-bottom:20px;grid-template-columns:56% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/www.heliotis.com\/wp-content\/uploads\/2026\/03\/phoenix_topo.png\" alt=\"\" class=\"wp-image-25564 size-full\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\"><em>Figure 3: Raw contour\/edge points \u2013 pixel grid discretization is visible<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n<\/div><\/div>\n\n<h3 class=\"wp-block-heading\">4.2 Subpixel Edge Points and Circle Fit<\/h3>\n\n<p class=\"wp-block-paragraph\">In the next step, subpixel edge points are determined and a circle fit is performed over many points. Even if individual points are only &#8220;slightly subpixelated,&#8221; the combination of many points significantly stabilizes the estimate. <\/p>\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/www.heliotis.com\/wp-content\/uploads\/2026\/03\/contour_from_topo-1.png\" alt=\"\" class=\"wp-image-25570\" style=\"aspect-ratio:2.704350377815274;width:800px;height:auto\"\/><\/figure>\n\n<p class=\"wp-block-paragraph\"><em>Figure 4: Best-fit circle (Least Squares\/RLS) over the contour points<\/em><\/p>\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/www.heliotis.com\/wp-content\/uploads\/2026\/03\/contour_from_topo2.png\" alt=\"\" class=\"wp-image-25571\" style=\"aspect-ratio:2.241320605581565;width:800px;height:auto\"\/><\/figure>\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/www.heliotis.com\/wp-content\/uploads\/2026\/03\/contour_from_topo3.png\" alt=\"\" class=\"wp-image-25572\" style=\"aspect-ratio:2.2000781300865944;width:800px;height:auto\"\/><\/figure>\n\n<p class=\"wp-block-paragraph\"><br\/><em>Figure 5: Detail: Raw contour (pixelated) vs. fit (smooth) \u2013 subpixel principle of operation.<\/em><\/p>\n\n<h2 class=\"wp-block-heading\">5. Results: Repeatability<\/h2>\n\n<h3 class=\"wp-block-heading\">5.1 Measurement Plan<\/h3>\n\n<ul class=\"wp-block-list\">\n<li><strong>30 repetitions<\/strong> at the same location<\/li>\n\n\n\n<li>Evaluation of the <strong>6 cavities<\/strong> per image<\/li>\n\n\n\n<li>Parameters: Mean (\u00b5) and standard deviation (\u03c3) of the diameters<\/li>\n<\/ul>\n\n<h3 class=\"wp-block-heading\">5.2 Results<\/h3>\n\n<p class=\"wp-block-paragraph\">Combined across all cavities and repetitions, the results are:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Mean: <strong>\u00b5 = 3.043 mm<\/strong><\/li>\n\n\n\n<li>Standard deviation: <strong>\u03c3 = 0.0025 mm = 2.5 \u00b5m<\/strong><\/li>\n<\/ul>\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/www.heliotis.com\/wp-content\/uploads\/2026\/03\/phoenix_eval1-1024x475.png\" alt=\"\" class=\"wp-image-25575\"\/><\/figure>\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" src=\"https:\/\/www.heliotis.com\/wp-content\/uploads\/2026\/03\/phoenix_eval2.png\" alt=\"\" class=\"wp-image-25577\" style=\"aspect-ratio:1.2338611449451888;width:800px;height:auto\"\/><\/figure>\n\n<p class=\"wp-block-paragraph\"><em>Figure 6: Measured values per cavity over 30 repetitions<\/em><\/p>\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n<p class=\"wp-block-paragraph\">Findings:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Variation in the range of <strong>2\u20133 \u00b5m<\/strong> is consistent with &#8220;~1\/10th pixel&#8221; at ~30 \u00b5m pixel size.<\/li>\n\n\n\n<li>The mean value is close to the upper specification limit (USL = 3.05 mm). This is relevant for Cp\/Cpk. <\/li>\n<\/ul>\n\n<h2 class=\"wp-block-heading\">6. Process Capability Indices Cg and Cgk<\/h2>\n\n<p class=\"wp-block-paragraph\">The indices Cp\/Cpk are used here to categorize the measurement variation in relation to the tolerance and the position of the mean.<\/p>\n\n<h3 class=\"wp-block-heading\">6.1 Definitions<\/h3>\n\n<p class=\"wp-block-paragraph\"><strong>C<\/strong>g \u2192 &#8220;How wide is the tolerance in relation to the variation?&#8221;<\/p>\n\n<p class=\"wp-block-paragraph\"><strong>Cgk<\/strong> \u2192 &#8220;How much usable tolerance remains, considering the actual process position?&#8221;<\/p>\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><math display=\"block\"><semantics><mrow><msub><mi>C<\/mi><mi>g<\/mi><\/msub><mo>=<\/mo><mfrac><mrow><mi>U<\/mi><mi>S<\/mi><mi>L<\/mi><mo>\u2212<\/mo><mi>L<\/mi><mi>S<\/mi><mi>L<\/mi><\/mrow><mrow><mn>6<\/mn><mspace width=\"0.1667em\"><\/mspace><mi>\u03c3<\/mi><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">C_g = \\frac{USL &#8211; LSL}{6\\,\\sigma}<\/annotation><\/semantics><\/math><br\/><math display=\"block\"><semantics><mrow><msub><mi>C<\/mi><mrow><mi>g<\/mi><mi>k<\/mi><\/mrow><\/msub><mo>=<\/mo><mrow><mi>min<\/mi><mo>\u2061<\/mo><\/mrow><mrow><mo fence=\"true\" form=\"prefix\">(<\/mo><mfrac><mrow><mi>U<\/mi><mi>S<\/mi><mi>L<\/mi><mo>\u2212<\/mo><mi>\u03bc<\/mi><\/mrow><mrow><mn>3<\/mn><mspace width=\"0.1667em\"><\/mspace><mi>\u03c3<\/mi><\/mrow><\/mfrac><mo separator=\"true\">,<\/mo><mfrac><mrow><mi>\u03bc<\/mi><mo>\u2212<\/mo><mi>L<\/mi><mi>S<\/mi><mi>L<\/mi><\/mrow><mrow><mn>3<\/mn><mspace width=\"0.1667em\"><\/mspace><mi>\u03c3<\/mi><\/mrow><\/mfrac><mo fence=\"true\" form=\"postfix\">)<\/mo><\/mrow><\/mrow><annotation encoding=\"application\/x-tex\">C_{gk} = \\min \\left( \\frac{USL &#8211; \\mu}{3\\,\\sigma}, \\frac{\\mu &#8211; LSL}{3\\,\\sigma} \\right)<\/annotation><\/semantics><\/math><\/td><td><math display=\"block\"><semantics><mtable displaystyle=\"true\" columnalign=\"right left\" class=\"tml-jot\"><mtr><mtd class=\"tml-right\" style=\"padding-left:0em;padding-right:0em;\"><mrow><mi>U<\/mi><mi>S<\/mi><mi>L<\/mi><\/mrow><\/mtd><mtd class=\"tml-left\" style=\"padding-left:0em;padding-right:0em;\"><mrow><mo>=<\/mo><mtext>Upper Specification Limit<\/mtext><\/mrow><\/mtd><\/mtr><mtr><mtd class=\"tml-right\" style=\"padding-left:0em;padding-right:0em;\"><mrow><mi>L<\/mi><mi>S<\/mi><mi>L<\/mi><\/mrow><\/mtd><mtd class=\"tml-left\" style=\"padding-left:0em;padding-right:0em;\"><mrow><mo>=<\/mo><mtext>Lower Specification Limit<\/mtext><\/mrow><\/mtd><\/mtr><mtr><mtd class=\"tml-right\" style=\"padding-left:0em;padding-right:0em;\"><mi>\u03bc<\/mi><\/mtd><mtd class=\"tml-left\" style=\"padding-left:0em;padding-right:0em;\"><mrow><mo>=<\/mo><mtext>Process Mean<\/mtext><\/mrow><\/mtd><\/mtr><mtr><mtd class=\"tml-right\" style=\"padding-left:0em;padding-right:0em;\"><mi>\u03c3<\/mi><\/mtd><mtd class=\"tml-left\" style=\"padding-left:0em;padding-right:0em;\"><mrow><mo>=<\/mo><mtext>Standard Deviation<\/mtext><\/mrow><\/mtd><\/mtr><\/mtable><annotation encoding=\"application\/x-tex\">\\begin{aligned} USL &amp;= \\text{Upper Specification Limit} \\\\ LSL &amp;= \\text{Lower Specification Limit} \\\\ \\mu &amp;= \\text{Process Mean} \\\\ \\sigma &amp;= \\text{Standard Deviation} \\end{aligned}<\/annotation><\/semantics><\/math><\/td><\/tr><\/tbody><\/table><\/figure>\n\n<h3 class=\"wp-block-heading\">6.2 Inserting the Values<\/h3>\n\n<ul class=\"wp-block-list\">\n<li>LSL = 2.95 mm<\/li>\n\n\n\n<li>USL = 3.05 mm<\/li>\n\n\n\n<li>Tolerance width = 0.10 mm<\/li>\n\n\n\n<li>\u03c3 = 0.0025 mm \u21d2 6\u03c3 = 0.015 mm, 3\u03c3 = 0.0075 mm<\/li>\n\n\n\n<li>\u00b5 = 3.043 mm<\/li>\n<\/ul>\n\n<p class=\"wp-block-paragraph\"><strong>Cg:<\/strong><br\/>Cp = 0.10 \/ 0.015 \u2248 <strong>6.67<\/strong><\/p>\n\n<p class=\"wp-block-paragraph\"><strong>Cgk:<\/strong><br\/>(USL \u2212 \u00b5) \/ (3\u03c3) = (3.05 \u2212 3.043) \/ 0.0075 \u2248 <strong>0.93<\/strong><br\/>(\u00b5 \u2212 LSL) \/ (3\u03c3) = (3.043 \u2212 2.95) \/ 0.0075 \u2248 <strong>12.4<\/strong><br\/>Cgk = min(0.93; 12.4) = <strong>0.93<\/strong><\/p>\n\n<h3 class=\"wp-block-heading\">6.3 Interpretation<\/h3>\n\n<ul class=\"wp-block-list\">\n<li><strong>Cg very high:<\/strong> The variation is very small in relation to the tolerance \u2192 very precise measurement.<\/li>\n\n\n\n<li><strong>Cgk significantly smaller than Cg:<\/strong> The mean is close to USL. This does not indicate &#8220;too much noise,&#8221; but rather <strong>positioning\/offset<\/strong> (e.g., real component slightly oversize, calibration, thresholds, fit bias). <\/li>\n<\/ul>\n\n<h2 class=\"wp-block-heading\">7. Practical Tips: How to reliably achieve subpixel performance<\/h2>\n\n<p class=\"wp-block-paragraph\">Subpixel accuracy comes from good imaging conditions\u2014not from &#8220;magic&#8221;:<\/p>\n\n<ol class=\"wp-block-list\">\n<li><strong>High, stable contrast<\/strong> at the edge (no flare artifacts)<\/li>\n\n\n\n<li><strong>No saturation<\/strong> (do not clip profiles)<\/li>\n\n\n\n<li><strong>Good focus \/ stable optics<\/strong> (MTF)<\/li>\n\n\n\n<li><strong>Good SNR<\/strong> (appropriate exposure, stable lighting)<\/li>\n\n\n\n<li><strong>Robust fit<\/strong> (sufficient points, plausible model)<\/li>\n\n\n\n<li><strong>Constant evaluation parameters<\/strong> (otherwise the bias drifts)<\/li>\n<\/ol>\n\n<h2 class=\"wp-block-heading\">8. Conclusion<\/h2>\n\n<p class=\"wp-block-paragraph\">This example shows why lateral measurements are not limited to pixel size: By distributing the signal over several pixels, the position of edges and geometries derived from them can be determined at a subpixel level. In the measurement series, we achieve a repeatability of <strong>\u03c3 \u2248 2.5 \u00b5m<\/strong>, even though the lateral pixel size is approximately <strong>30 \u00b5m<\/strong>. <\/p>\n\n<p class=\"wp-block-paragraph\">The lateral pixel size is not the physical limit of measurement accuracy\u2014it is merely the sampling basis of a continuous signal.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;A pixel is the smallest measurable lateral unit.&#8221; This is true for pure pixel counting\u2014but not for determining the position of edges, lines, or centers. <\/p>\n","protected":false},"author":4,"featured_media":28356,"template":"","class_list":["post-29165","tutorial","type-tutorial","status-publish","has-post-thumbnail","hentry"],"_links":{"self":[{"href":"https:\/\/www.heliotis.com\/en\/wp-json\/wp\/v2\/tutorial\/29165","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.heliotis.com\/en\/wp-json\/wp\/v2\/tutorial"}],"about":[{"href":"https:\/\/www.heliotis.com\/en\/wp-json\/wp\/v2\/types\/tutorial"}],"author":[{"embeddable":true,"href":"https:\/\/www.heliotis.com\/en\/wp-json\/wp\/v2\/users\/4"}],"version-history":[{"count":1,"href":"https:\/\/www.heliotis.com\/en\/wp-json\/wp\/v2\/tutorial\/29165\/revisions"}],"predecessor-version":[{"id":29166,"href":"https:\/\/www.heliotis.com\/en\/wp-json\/wp\/v2\/tutorial\/29165\/revisions\/29166"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.heliotis.com\/en\/wp-json\/wp\/v2\/media\/28356"}],"wp:attachment":[{"href":"https:\/\/www.heliotis.com\/en\/wp-json\/wp\/v2\/media?parent=29165"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}