Calculates the center of gravity (COG) of a character-like binary image based on potential energy.
cog_potential(img, origin = c("bottomleft", "topleft"))A list containing:
statisticsA data frame with the following components:
center_x, center_y: The (x, y) coordinates of the COG in pixel coordinates of the input image.
center_x_trim, center_y_trim: The COG coordinates relative to the trimmed glyph region, excluding image margins.
center_x_std, center_y_std: The standardized COG coordinates ranging from 0 to 1, based on the trimmed region's width and height.
margin_left, margin_right, margin_top, margin_bottom: Margins between the glyph and the image boundary.
width_original, height_original: Dimensions of the original image.
width_trim, height_trim: Width and height of the trimmed glyph region, excluding margins.
potentialsA data frame containing the (x, y) coordinates and the normalized potential value for each pixel within the convex hull. The potentials are normalized so that their sum equals 1.
An image input, either a file path to an image file (e.g., PNG, JPEG),
or a cimg object from the imager package. The image should be in binary form,
with foreground (glyph) values not equal to 1 and background values equal to 1.
A character string indicating the location of the image origin.
Use "bottomleft" (default) if the y-axis increases upward (Cartesian),
or "topleft" if the y-axis increases downward (as in image arrays).
In the potential energy-based method, the center of gravity (COG) is defined as the weighted mean of the coordinates of all pixels within the convex hull of the stroke region, where the weight at each pixel is determined by the potential induced by all other stroke pixels. The method assumes that each stroke pixel contributes a unit mass and exerts an attractive force on all other pixels within the convex polygon, inversely proportional to their distance, modeling a simplified gravitational interaction. To avoid excessive computation, unintended influence from remote regions, and to restrict the analysis to a perceptually relevant area, the potential is computed only within the convex polygon (i.e., the same region used in the contour-based COG calculation), rather than across the entire image.
Let \(S\) be the set of all stroke pixels, and let \(R\) be the set of all pixels within the convex polygon region. The potential at each pixel \((x, y) \in R\) is defined as:
$$ p(x, y) = \sum_{\substack{(x', y') \in S \\ (x', y') \ne (x, y)}} \frac{1}{\sqrt{(x - x')^2 + (y - y')^2}} $$
That is, the potential at each point in \(R\) is the sum of the inverse distances to all stroke pixels in \(S\), excluding the case where \((x', y') = (x, y)\). Pixels outside the convex polygon are assigned a potential value of zero and do not contribute to the COG calculation.
Then, the center of gravity is computed as:
$$ G_x = \left( \sum_{(x, y) \in R} p(x, y) \cdot x \right) / \left( \sum_{(x, y) \in R} p(x, y) \right) $$ $$ G_y = \left( \sum_{(x, y) \in R} p(x, y) \cdot y \right) / \left( \sum_{(x, y) \in R} p(x, y) \right) $$
In other words, the COG corresponds to the weighted mean of pixel coordinates in the convex region, where weights are given by their potential values induced by the distribution of stroke pixels.
This method was originally proposed by Kotani et al. (2006) and has been used in character analysis and font design to reflect the perceived shape of glyphs more robustly than simple stroke averaging, and to further improve upon the contour-based COG by incorporating the spatial distribution of strokes within the convex polygon, thereby aligning more closely with the subjective impression of a character's center.
Kotani, A., Tanemura, Y., Mitsuyama, Y., Asai, Y., Nakamura, Y., & Onoye, T. (2006). Potential energy-based center of gravity evaluation of characters. The Journal of the Institute of Image Electronics Engineers of Japan, 35(4), 296–305. tools:::Rd_expr_doi("10.11371/iieej.35.296")
# \donttest{
data(img_A) # load example image from the package
result <- cog_potential(img_A, origin = "bottomleft")
result$statistics # summary data frame
head(result$potentials) # pixel coordinates with normalized potential values
result$origin # image origin specification
# }
Run the code above in your browser using DataLab