two image in two openmv board similiarity compared

Hi,Every one! I had two openmv h7 board. one(A board) be fixed left side ,the other one(B board) be fixed right,but how to compare the two image similiarity and transfer image A board image to B board,B board received A board iamge Usart information ,then converted them to Image information? Thanks!

https://github.com/openmv/openmv/blob/master/scripts/examples/34-Remote-Control/image_transfer_raw_as_the_controller_device.py

https://github.com/openmv/openmv/blob/master/scripts/examples/34-Remote-Control/image_transfer_raw_as_the_remote_device.py

Then use the image similarly method to compare the two.

@ kwagyeman ,Thanks! That is what I wanted. But I found ,at QVGA mode,it only 4 FPS. I only get the QVGA mode special point value. How to speed up the FPS.Thanks! In follow this code ,I want to transfer img17 to othe board, it only 20 x 16 point.
slave code:

# Image Transfer - As The Remote Device
#
# This script is made to pair with another OpenMV Cam running "image_transfer_raw_as_the_controller_device.py"
#
# This script shows off how to transfer the frame buffer from one OpenMV Cam to another.

import image, network, rpc, sensor, struct
import utime

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)

# The RPC library above is installed on your OpenMV Cam and provides mutliple classes for
# allowing your OpenMV Cam to be controlled over CAN, I2C, SPI, UART, or WIFI.

################################################################
# Choose the interface you wish to control your OpenMV Cam over.
################################################################

# Uncomment the below line to setup your OpenMV Cam for control over CAN.
#
# * message_id - CAN message to use for data transport on the can bus (11-bit).
# * bit_rate - CAN bit rate.
# * sampling_point - Tseg1/Tseg2 ratio. Typically 75%. (50.0, 62.5, 75.0, 87.5, etc.)
#
# NOTE: Master and slave message ids and can bit rates must match. Connect master can high to slave
#       can high and master can low to slave can lo. The can bus must be terminated with 120 ohms.
#
# interface = rpc.rpc_can_slave(message_id=0x7FF, bit_rate=1000000, sampling_point=75.0)

# Uncomment the below line to setup your OpenMV Cam for control over I2C.
#
# * slave_addr - I2C address.
#
# NOTE: Master and slave addresses must match. Connect master scl to slave scl and master sda
#       to slave sda. You must use external pull ups. Finally, both devices must share a ground.
#
# interface = rpc.rpc_i2c_slave(slave_addr=0x12)

# Uncomment the below line to setup your OpenMV Cam for control over SPI.
#
# * cs_pin - Slave Select Pin.
# * clk_polarity - Idle clock level (0 or 1).
# * clk_phase - Sample data on the first (0) or second edge (1) of the clock.
#
# NOTE: Master and slave settings much match. Connect CS, SCLK, MOSI, MISO to CS, SCLK, MOSI, MISO.
#       Finally, both devices must share a common ground.
#
# interface = rpc.rpc_spi_slave(cs_pin="P3", clk_polarity=1, clk_phase=0)

# Uncomment the below line to setup your OpenMV Cam for control over UART.
#
# * baudrate - Serial Baudrate.
#
# NOTE: Master and slave baud rates must match. Connect master tx to slave rx and master rx to
#       slave tx. Finally, both devices must share a common ground.
#
interface = rpc.rpc_uart_slave(baudrate=7500000)


def timeit(f, *args, **kwargs):
    func_name = str(f).split(' ')[1]
    def new_func(*args, **kwargs):
        t = utime.ticks_us()
        result = f(*args, **kwargs)
        print('execution time: ', utime.ticks_diff(utime.ticks_us(), t), ' us')
        return result
    return new_func


def img_process(img):
    '''
    Get Boll Point image 
    '''

    img1 = img.copy(roi = (181,40,40,2), x_scale = 1.0, y_scale = 1.0)
    img1_cp = img1.mean_pooled(2,2)
    img.draw_image(img1_cp,0,0)


    img2 = img.copy(roi = (181,82,40,2), x_scale = 1.0, y_scale = 1.0)
    img2_cp = img2.mean_pooled(2,2)
    img.draw_image(img2_cp,0,1)


    img3 = img.copy(roi = (181,114,40,2),x_scale = 1.0, y_scale = 1.0)
    img3_cp = img3.mean_pooled(2,2)
    img.draw_image(img3_cp,0,2)




    for i in range(1,21):

        img4 = img.copy(roi = ((171+(i-1)*3),140,2,2),x_scale = 1.0, y_scale = 1.0)
        img4_cp = img4.mean_pool(2,2)
        img.draw_image(img4_cp, i-1, 3)




    for i in range(1,21):
        img5 = img.copy(roi = ((171+(i-1)*3),160,2,2),x_scale = 1.0, y_scale = 1.0)
        img5_cp = img5.mean_pooled(2,2)
        img.draw_image(img5_cp, (i-1), 4)




    for i in range(1,21):
        img6 = img.copy(roi = ((161+(i-1)*4),176,2,2),x_scale = 1.0, y_scale = 1.0)
        img6_cp = img6.mean_pooled(2,2)
        img.draw_image(img6_cp, i-1, 5)


    for i in range(1,21):
        img7 = img.copy(roi =((161+ (i-1)*4),189, 2,2),x_scale =1.0, y_scale = 1.0)
        img7_cp = img7.mean_pooled(2,2)
        img.draw_image(img7_cp, i-1, 6)


    for i in range(1,21):
        img8 = img.copy(roi = ((151 + (i-1)*4),200, 2,3),x_scale =1.0, y_scale = 1.0)
        img8_cp = img8.mean_pooled(2,3)
        img.draw_image(img8_cp, i-1, 7)

 
    for i in range(1,21):
        img9 = img.copy(roi = ((141+ (i-1)*5),208, 2,3),x_scale =1.0, y_scale = 1.0)
        img9_cp = img9.mean_pooled(2,3)
        img.draw_image(img9_cp, i-1, 8)


    for i in range(1,21):
        img10 = img.copy(roi = ((131+(i-1)*5),214, 2,4),x_scale =1.0, y_scale = 1.0)
        img10_cp = img10.mean_pooled(2,4)
        img.draw_image(img10_cp, i-1, 9)


    for i in range(1,21):
        img11 = img.copy(roi = ((121 +(i-1)*6),220, 2,4),x_scale =1.0, y_scale = 1.0)
        img11_cp = img11.mean_pooled(2,4)
        img.draw_image(img11_cp, i-1, 10)


    for i in range(1,21):
        img12 = img.copy(roi = ((111 +(i-1)*6),224,2,5),x_scale =1.0, y_scale = 1.0)
        img12_cp = img12.mean_pooled(2,5)
        img.draw_image(img12_cp, i-1, 11)


    for i in range(1,21):
        img13 = img.copy(roi = ((101+ (i-1) * 7),227, 2,5), x_scale = 1.0, y_scale = 1.0)
        img13_cp = img13.mean_pooled(2,5)
        img.draw_image(img13_cp, i-1, 12)


    for i in range(1,21):
        img14 = img.copy(roi = ((91 + (i-1) * 7),230, 2, 6),x_scale = 1.0, y_scale = 1.0)
        img14_cp = img14.mean_pooled(2,6)
        img.draw_image(img14_cp, i-1, 13)


    for i in range(1,21):
        img15 = img.copy(roi = ((81 + (i-1) *8 ),232, 2, 6),x_scale = 1.0, y_scale = 1.0)
        img15_cp = img15.mean_pooled(2,6)
        img.draw_image(img15_cp, i-1, 14)


    for i in range(1,21):
        img16 = img.copy(roi = ((81 + (i-1) * 7),234, 2, 6),x_scale = 1.0, y_scale = 1.0)
        img16_cp = img16.mean_pooled(2,6)
        img.draw_image(img16_cp , i-1, 15)



    img17 = img.copy(roi = (0, 0,20, 16), x_scale = 1.0, y_scale = 1.0)
    img.clear()

    img.draw_image(img17, 100,100,x_scale = 1.0, y_scale = 1.0)        # put image to PyImage

    return img17



################################################################
# Call Backs
################################################################

# When called sets the pixformat and framesize, takes a snapshot
# and then returns the frame buffer shape to store the image in.
#
# data is a 4 byte pixformat and 4 byte framesize.

def raw_image_snapshot(data):
    pixformat, framesize = struct.unpack("<II", data)
    sensor.set_pixformat(pixformat)
    sensor.set_framesize(framesize)
    img = sensor.snapshot()
    
    pImage = img_process(img)
    return struct.pack("<IIII", sensor.width(), sensor.height(), sensor.get_pixformat(), pImage.size())
    #return struct.pack("<IIII", 16, 20, sensor.get_pixformat(), pImage.size())

def raw_image_read_cb():
    interface.put_bytes(sensor.get_fb().bytearray(), 50) # timeout

# Read data from the frame buffer given a offset and size.
# If data is empty then a transfer is scheduled after the RPC call finishes.
#
# data is a 4 byte size and 4 byte offset.

def raw_image_read(data):
    if not len(data):
        interface.schedule_callback(raw_image_read_cb)
        return bytes()
    else:
        offset, size = struct.unpack("<II", data)
        return memoryview(sensor.get_fb().bytearray())[offset:offset+size]

# Register call backs.

interface.register_callback(raw_image_snapshot)
interface.register_callback(raw_image_read)

# Once all call backs have been registered we can start
# processing remote events. interface.loop() does not return.

interface.loop()

master code:

# Image Transfer - As The Controller Device
#
# This script is made to pair with another OpenMV Cam running "image_transfer_raw_as_the_remote_device.py"
#
# This script shows off how to transfer the frame buffer from one OpenMV Cam to another.

import image, network, omv, rpc, sensor, struct, time
import utime


def timeit(f, *args, **kwargs):
    func_name = str(f).split(' ')[1]
    def new_func(*args, **kwargs):
        t = utime.ticks_us()
        result = f(*args, **kwargs)
        print('execution time: ', utime.ticks_diff(utime.ticks_us(), t), ' us')
        return result
    return new_func

# The RPC library above is installed on your OpenMV Cam and provides mutliple classes for
# allowing your OpenMV Cam to control over CAN, I2C, SPI, UART, or WIFI.

##############################################################
# Choose the interface you wish to control an OpenMV Cam over.
##############################################################

# Uncomment the below line to setup your OpenMV Cam for controlling over CAN.
#
# * message_id - CAN message to use for data transport on the can bus (11-bit).
# * bit_rate - CAN bit rate.
# * sampling_point - Tseg1/Tseg2 ratio. Typically 75%. (50.0, 62.5, 75.0, 87.5, etc.)
#
# NOTE: Master and slave message ids and can bit rates must match. Connect master can high to slave
#       can high and master can low to slave can lo. The can bus must be terminated with 120 ohms.
#
# interface = rpc.rpc_can_master(message_id=0x7FF, bit_rate=1000000, sampling_point=75.0)

# Uncomment the below line to setup your OpenMV Cam for controlling over I2C.
#
# * slave_addr - I2C address.
# * rate - I2C Bus Clock Frequency.
#
# NOTE: Master and slave addresses must match. Connect master scl to slave scl and master sda
#       to slave sda. You must use external pull ups. Finally, both devices must share a ground.
#
# interface = rpc.rpc_i2c_master(slave_addr=0x12, rate=1000000)

# Uncomment the below line to setup your OpenMV Cam for controlling over SPI.
#
# * cs_pin - Slave Select Pin.
# * freq - SPI Bus Clock Frequency
# * clk_polarity - Idle clock level (0 or 1).
# * clk_phase - Sample data on the first (0) or second edge (1) of the clock.
#
# NOTE: Master and slave settings much match. Connect CS, SCLK, MOSI, MISO to CS, SCLK, MOSI, MISO.
#       Finally, both devices must share a common ground.
#

# interface = rpc.rpc_spi_master(cs_pin="P3", freq=20000000, clk_polarity=1, clk_phase=0)

# Uncomment the below line to setup your OpenMV Cam for controlling over UART.
#
# * baudrate - Serial Baudrate.
#
# NOTE: Master and slave baud rates must match. Connect master tx to slave rx and master rx to
#       slave tx. Finally, both devices must share a common ground.
#
interface = rpc.rpc_uart_master(baudrate=7500000)

##############################################################
# Call Back Handlers
##############################################################
@timeit
def get_frame_buffer_call_back(pixformat, framesize, cutthrough, silent):
    if not silent: print("Getting Remote Frame...")

    result = interface.call("raw_image_snapshot", struct.pack("<II", pixformat, framesize))
    if result is not None:

        w, h, pixformat, size = struct.unpack("<IIII", result)
        img = image.Image(w, h, pixformat, copy_to_fb=True) # Alloc cleared frame buffer.

        if cutthrough:
            # Fast cutthrough data transfer with no error checking.

            # Before starting the cut through data transfer we need to sync both the master and the
            # slave device. On return both devices are in sync.
            result = interface.call("raw_image_read")
            if result is not None:

                # GET BYTES NEEDS TO EXECUTE NEXT IMMEDIATELY WITH LITTLE DELAY NEXT.

                # Read all the image data in one very large transfer.
                interface.get_bytes(img.bytearray(), 50) # timeout

        else:
            # Slower data transfer with error checking.

            # Transfer 32/8 KB chunks.
            chunk_size = (1 << 15) if omv.board_type() == "H7" else (1 << 13)

            if not silent: print("Reading %d bytes..." % size)
            for i in range(0, size, chunk_size):
                ok = False
                for j in range(3): # Try up to 3 times.
                    result = interface.call("raw_image_read", struct.pack("<II", i, chunk_size))
                    if result is not None:
                        img.bytearray()[i:i+chunk_size] = result # Write the image data.
                        if not silent: print("%.2f%%" % ((i * 100) / size))
                        ok = True
                        break
                    if not silent: print("Retrying... %d/2" % (j + 1))
                if not ok:
                    if not silent: print("Error!")
                    return None

        return img

    else:
        if not silent: print("Failed to get Remote Frame!")

    return None






clock = time.clock()
while(True):
    clock.tick()

    # You may change the pixformat and the framesize of the image transfered from the remote device
    # by modifying the below arguments.
    #
    # When cutthrough is False the image will be transferred through the RPC library with CRC and
    # retry protection on all data moved. For faster data transfer set cutthrough to True so that
    # get_bytes() and put_bytes() are called after an RPC call completes to transfer data
    # more quicly from one image buffer to another. Note: This works because once an RPC call
    # completes successfully both the master and slave devices are synchronized completely.
    #
    img = get_frame_buffer_call_back(sensor.RGB565, sensor.QVGA, cutthrough=True, silent=True)
    if img is not None:
        pass # You can process the image here.
        #img.draw_image(img, 100,100,x_scale = 1.0, y_scale = 1.0)

    print(clock.fps())

Use SPI. There’s no magic here. Calculate the bitrate you need and you’ll see that you need to make it in a very high MHZ number if you want to move a raw image at a particular FPS.

Otherwise, crop the image and make it smaller.