How to get the 3D coordinates of the visible vertices in a rendered image in Blender
A partial solution, due to some approximation in ray cast (or some bug in my script?).

This solution uses 'world_to_camera_view' from bpy_extras.object_utils module. 'world_to_camera_view' returns the projection of a vertex in camera's coordinates, which means that the vertex is inside the camera view if the projected coordinates are between 0 and 1.

From that, the script is testing if the corresponding vertex is visible from the camera (and not hidden by another part of the mesh). To do that, it's using a ray cast from the camera location to the vertex.

Unfortunately, some of these ray casts fail... but this script is close to your need and that's why I provide it as an answer.

Hope that can help though.

import bpy
from mathutils import Vector
from mathutils.bvhtree import BVHTree
from bpy_extras.object_utils import world_to_camera_view

# Create a BVH tree and return bvh and vertices in world coordinates 
def BVHTreeAndVerticesInWorldFromObj( obj ):
    mWorld = obj.matrix_world
    vertsInWorld = [mWorld * v.co for v in obj.data.vertices]

    bvh = BVHTree.FromPolygons( vertsInWorld, [p.vertices for p in obj.data.polygons] )

    return bvh, vertsInWorld

# Deselect mesh polygons and vertices
def DeselectEdgesAndPolygons( obj ):
    for p in obj.data.polygons:
        p.select = False
    for e in obj.data.edges:
        e.select = False

# Get context elements: scene, camera and mesh
scene = bpy.context.scene
cam = bpy.data.objects['Camera']
obj = bpy.data.objects['Cube']

# Threshold to test if ray cast corresponds to the original vertex
limit = 0.0001

# Deselect mesh elements
DeselectEdgesAndPolygons( obj )

# In world coordinates, get a bvh tree and vertices
bvh, vertices = BVHTreeAndVerticesInWorldFromObj( obj )

print( '-------------------' )

for i, v in enumerate( vertices ):
    # Get the 2D projection of the vertex
    co2D = world_to_camera_view( scene, cam, v )

    # By default, deselect it
    obj.data.vertices[i].select = False

    # If inside the camera view
    if 0.0 &lt;= co2D.x &lt;= 1.0 and 0.0 &lt;= co2D.y &lt;= 1.0: 
        # Try a ray cast, in order to test the vertex visibility from the camera
        location, normal, index, distance = bvh.ray_cast( cam.location, (v - cam.location).normalized() )
        # If the ray hits something and if this hit is close to the vertex, we assume this is the vertex
        if location and (v - location).length &lt; limit:
            obj.data.vertices[i].select = True

del bvh