A method that seems to provide adequately good estimation - which can prove extremely accurate having ensured the precision of your input values, was derived from this article where it explains that having known the specifications of your sensor(sensor's width-height, output resolution), and your focal length, without taking the zoom factor into consideration, you can calculate size of an object in meters or in pixels given one of them correspondingly. This is achieved by calculating the pixels that an object occupies on the sensor followed by a linear conversion between real and pixel size depending on what you need. Furthermore, having known the size of an object in both real world (meters) and within the frame (pixels), you can also calculate the distance from it.
The following piece of code is tested and it provides an approximation - slightly deviated from the measured values - which imo is quite satisfactory - and as the article mentions - the precision of the input is critical.
#Requires 1)Real object size, 2)Distance from object and returns ---> Object_size in pixels
def given_real_get_pixels(Object_width_meters,Object_height_meters,distance):
Object_height_on_sensor_mms=(Focal_length*Object_height_meters)/distance
#Object_height_on_sensor_mms2
Object_height_pixels=(Sensor_height_pixels*Object_height_on_sensor_mms)/Sensor_height_mms
Object_width_on_sensor_mms=(Focal_length*Object_width_meters)/distance
Object_width_pixels=(Sensor_width_pixels*Object_width_on_sensor_mms)/Sensor_width_mms
print(f'Object_actual_size={Object_width_meters} x {Object_height_meters}(meters) at {distance}(meters) distance coresponds to Object_pixel_size={Object_width_pixels} x {Object_height_pixels}(pixels)')
return Object_height_pixels,Object_width_pixels
#Requires 1)distance from object, 2)Object height in pixels and returns ---> Object_size in meters
def given_pixels_get_real(distance,Object_height_pixels,Object_width_pixels):
Object_height_on_sensor_mms=(Sensor_height_mms*Object_height_pixels)/Sensor_height_pixels
Object_height_meters=((distance*Object_height_on_sensor_mms)/Focal_length)
Object_width_on_sensor_mms=(Sensor_width_mms*Object_width_pixels)/Sensor_width_pixels
Object_width_meters=((distance*Object_width_on_sensor_mms)/Focal_length)
print(f'Object_pixel_size={Object_width_pixels} x {Object_height_pixels}(pixels) at {distance}(meters) distance corresponds to Object_actual_size={Object_width_meters} x {Object_height_meters}(meters)')
return Object_height_meters,Object_width_meters
def given_real_and_pixels_get_distance(Object_width_meters,Object_height_meters,Object_width_pixels,Object_height_pixels):
Object_height_on_sensor_mms=(Sensor_height_mms*Object_height_pixels)/Sensor_height_pixels
distance_height=(Focal_length*Object_height_meters)/Object_height_on_sensor_mms
Object_width_on_sensor_mms=(Sensor_width_mms*Object_width_pixels)/Sensor_width_pixels
distance_width=(Focal_length*Object_width_meters)/Object_width_on_sensor_mms
print(f'For obtaining an Object_pixel_size={Object_width_pixels} x {Object_height_pixels}(pixels) of an object that has Object_actual_size={Object_width_meters} x {Object_height_meters}(meters), distance must be distance_width = {distance_width}(meters) and distance_height= {distance_height}(meters) and mean_distance(suggested)={(distance_width+distance_height)/2}(meters) ')
return distance_width,distance_height
#################################################### Define Specifications ######################################################
#Sensor
Sensor_width_mms=7.410 #mm
Sensor_height_mms=4.980 #mm
Sensor_width_pixels=3088 #pixels
Sensor_height_pixels=2076 #pixels
#Focal length
Focal_length=9.6 #mm
######################################################### Define Parameters ######################################################
distance=125 #0.8 # meters
################################################# GET OBJECT SIZE IN PIXELS ######################################################
Object_width_meters=Object_height_meters=0.001 #meters
Object_height_pixels,Object_width_pixels=given_real_get_pixels(Object_width_meters,Object_height_meters,distance)
################################################# GET OBJECT SIZE IN METERS ######################################################
Object_width_pixels=Object_height_pixels=20
Object_height_meters,Object_width_meters=given_pixels_get_real(distance,Object_height_pixels,Object_width_pixels)
########################################### GET DISTANCE TO OBJECT IN METERS ######################################################
Object_width_meters=0.0005
Object_height_meters=0.001 #meters
Object_width_pixels=10
Object_height_pixels=20
distance_width,distance_height=given_real_and_pixels_get_distance(Object_width_meters,Object_height_meters,Object_width_pixels,Object_height_pixels)
Just to mention - the naming of the variables may be cumbersome but not without a good reason .. To explain a bit, all methods consider both width and height but the calculations for each one of them are implemented independently ..