<!-- set up a variable to check whether an image also has a caption associated with it... -->
<txp:variable name="caption" value='<txp:image_info />' />

<!-- ...now use that image caption and wrap img inside a figure with figcaption tags, otherwise just use a plain img tag -->
<txp:if_variable name="caption" value="">

    <p itemprop="image" itemscope itemtype="https://schema.org/ImageObject">
        <img loading="lazy" itemprop="url contentUrl" src="<txp:image_url link='0' />" alt="<txp:image_info type='alt' />">
        <meta itemprop="width" content="<txp:image_info type="w" />">
        <meta itemprop="height" content="<txp:image_info type="h" />">
    </p>

<txp:else />

    <figure itemprop="image" itemscope itemtype="https://schema.org/ImageObject">

        <img loading="lazy" itemprop="url contentUrl" src="<txp:image_url link='0' />" alt="<txp:image_info type='alt' />">
        <meta itemprop="width" content="<txp:image_info type="w" />">
        <meta itemprop="height" content="<txp:image_info type="h" />">

        <!-- you do not need to specify the attribute type="caption" as that is the default setting for <txp:image_info /> tag -->
        <figcaption itemprop="caption">
            <txp:image_info />
        </figcaption>

    </figure>

</txp:if_variable>