Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
Collapse
Brand Logo

ModalAI Forum

A

AndriiHlyvko

@AndriiHlyvko
Contributor
Unfollow Follow
About
Posts
48
Topics
13
Shares
0
Groups
1
Followers
0
Following
0

Posts

Recent Best Controversial

  • Stereo camera calibration not working during extrinsics
    A AndriiHlyvko

    Also I had to manually switch the camera IDs in the file voxl-camera-server.conf because the left and right cameras were swapped. The camera calibration tool was reporting a negative distance between cameras.

    {
    			"name":	"stereo",
    			"enabled":	true,
    			"frame_rate":	30,
    			"type":	"ov7251",
    			"camera_id":	1,
    			"camera_id_second":	0,
    			"independent_exposure":	false,
    			"ae_desired_msv":	60,
    			"ae_filter_alpha":	0.600000023841858,
    			"ae_ignore_fraction":	0.20000000298023224,
    			"ae_slope":	0.05000000074505806,
    			"ae_exposure_period":	1,
    			"ae_gain_period":	1
    		}
    
    Ask your questions right here!

  • voxl-camera-server more exif metadata bugs
    A AndriiHlyvko

    @Zachary-Lowell-0 I managed to fix the code. Essentially I was updating the already existing jpeg exif block. Here is my solution. Its a little messy cuz I haven't had the time to clean it up. But I tested and it works.
    Would you guys be interested in pulling in my changes?

    // Function to create a new tag or update an existing one
    static ExifEntry* create_or_update_tag(ExifData* exif, ExifIfd ifd, ExifTag tag, ExifFormat fmt, unsigned int size, unsigned int components) {
        ExifEntry* entry = exif_content_get_entry(exif->ifd[ifd], tag);
        if (!entry) {
            // Create a new entry if it doesn't exist
            printf("Creating entry: %d\n", (int)tag);
            //entry = exif_entry_new();
            entry = create_tag(exif, ifd, tag, size);
            entry->tag = tag;
            entry->components = components;
            entry->format = fmt;
            ///entry->data = (unsigned char*)malloc(size);
            //exif_content_add_entry(exif->ifd[ifd], entry);
            ///exif_entry_unref(entry);
        } else {
            // Update the existing entry
            if (entry->size < size) {
                // If the existing entry size is insufficient, reallocate memory
                entry->data = (unsigned char*)realloc(entry->data, size);
                entry->size = size;
            }
            entry->components = components;
            entry->format = fmt;
        }
        return entry;
    }
    
    void PerCameraMgr::ProcessSnapshotFrame(image_result result)
    {
        BufferBlock* bufferBlockInfo = bufferGetBufferInfo(&snap_bufferGroup, result.second.buffer);
    
        // first write to pipe if subscribed
        camera_image_metadata_t meta;
        if(getMeta(result.first, &meta)) {
            M_WARN("Trying to process encode buffer without metadata\n");
            return;
        }
    
        int start_index = 0;
        //int start_index2 = 0;
        uint8_t* src_data = (uint8_t*)bufferBlockInfo->vaddress;
        //int extractJpgSize = bufferBlockInfo->size;
        
        int extractJpgSize = find_jpeg_buffer_size(src_data, bufferBlockInfo->size, &start_index);
        
        assert(start_index == 0);
        
        //int _extractJpgSize = find_jpeg_buffer(src_data, bufferBlockInfo->size, &start_index2);
        
        // find APP1 block start and length
        size_t prev_exif_block_start_idx = 0;
        size_t prev_exif_block_size = find_exif_start(src_data, bufferBlockInfo->size, &prev_exif_block_start_idx);
    
        if(extractJpgSize == 1){
            M_ERROR("Real Size of JPEG is incorrect");
            return;
        }
    
        printf("Snapshot jpeg start: %6d len %8d\n", start_index, extractJpgSize);
    
    #ifndef APQ8096
        // Load the EXIF data from the file
        unsigned char *exif_data;
        unsigned int exif_data_len;
        ExifEntry *entry;
       
        // can create exif data from raw jpeg image
        ExifData* exif = exif_data_new_from_data(src_data, extractJpgSize);
        //ExifData *exif = createExifData();
        if (exif == nullptr) {
            printf("Issue getting exif data from origin\n");
            return;
        }
        exif_data_fix(exif);
        
        //printf("Exif data before mods\n");
        //exif_data_dump(exif);
        //printf("End Exif data before mods\n");
        /**
         * @brief Good description of exif format https://www.media.mit.edu/pia/Research/deepview/exif.html 
         * 
         */
        ExifByteOrder imageByteOrder = exif_data_get_byte_order(exif); /**< Each camera saves its Exif data in a different byte order */
        //gps_data_t gps_grabbed_info = grab_gps_info();
    
        // Code to add latitude to exif tag
        entry = create_or_update_tag(exif, EXIF_IFD_GPS, (ExifTag)EXIF_TAG_GPS_LATITUDE_REF, (ExifFormat)EXIF_FORMAT_ASCII, 2*sizeof(char), 1);
        if (_uav_state.lat_deg >= 0) {
            memcpy(entry->data, "N", sizeof(char));
        } else {
            memcpy(entry->data, "S", sizeof(char));
            _uav_state.lat_deg *= -1;
        }
        
        
        entry = create_or_update_tag(exif, EXIF_IFD_GPS, (ExifTag)EXIF_TAG_GPS_LATITUDE, (ExifFormat)EXIF_FORMAT_RATIONAL, 3*sizeof(ExifRational), 3);
    
        ExifLong degrees_lat = static_cast<ExifLong>(_uav_state.lat_deg);
        
        double fractional = (_uav_state.lat_deg - degrees_lat);
        ExifLong minutes_lat = static_cast<ExifLong>(fractional*60);
        
        fractional = (fractional*60) - minutes_lat;
        double seconds_lat = (fractional * 60);
        
        ExifRational degrees_r = { degrees_lat, 1 };
        ExifRational minutes_r = { minutes_lat, 1 };
        ExifRational seconds_r = { static_cast<ExifLong>(seconds_lat * 1000000), 1000000 }; // Increased precision for seconds
        
        exif_set_rational(entry->data, imageByteOrder, degrees_r);
        exif_set_rational(entry->data + sizeof(ExifRational), imageByteOrder, minutes_r);
        exif_set_rational(entry->data + 2 * sizeof(ExifRational), imageByteOrder, seconds_r);
    
        // Code to add longitude to exif tag
        entry = create_or_update_tag(exif, EXIF_IFD_GPS, (ExifTag)EXIF_TAG_GPS_LONGITUDE_REF, (ExifFormat)EXIF_FORMAT_ASCII, 2*sizeof(char), 1);
        if (_uav_state.lon_deg >= 0) {
            memcpy(entry->data, "E", sizeof(char));
        } else {
            memcpy(entry->data, "W", sizeof(char));
            _uav_state.lon_deg *= -1;
        }
    
        entry = create_or_update_tag(exif, EXIF_IFD_GPS, (ExifTag)EXIF_TAG_GPS_LONGITUDE, (ExifFormat)EXIF_FORMAT_RATIONAL, 3*sizeof(ExifRational), 3);
    
        ExifLong degrees_lon = static_cast<ExifLong>(_uav_state.lon_deg);
        
        fractional = (_uav_state.lon_deg - degrees_lon);
        ExifLong minutes_lon = static_cast<ExifLong>(fractional*60);
        
        fractional = (fractional*60) - minutes_lon;
        double seconds_lon = (fractional * 60);
        
        degrees_r = { degrees_lon, 1 };
        minutes_r = { minutes_lon, 1 };
        seconds_r = { static_cast<ExifLong>(seconds_lon * 1000000), 1000000 }; // Increased precision for seconds
        
        exif_set_rational(entry->data, imageByteOrder, degrees_r);
        exif_set_rational(entry->data + sizeof(ExifRational), imageByteOrder, minutes_r);
        exif_set_rational(entry->data + 2 * sizeof(ExifRational), imageByteOrder, seconds_r); 
    
        // Code to add altitude to exif tag
        entry = create_or_update_tag(exif, EXIF_IFD_GPS, (ExifTag)EXIF_TAG_GPS_ALTITUDE, (ExifFormat)EXIF_FORMAT_RATIONAL, sizeof(ExifRational), 1);
    
        double alt_lon = _uav_state.alt_msl_meters;
        unsigned int tmp = static_cast<unsigned int>(alt_lon * 1000);
        exif_set_rational(entry->data, imageByteOrder, (ExifRational){tmp, 1000});
        
        
        entry = create_or_update_tag(exif, EXIF_IFD_GPS, (ExifTag)EXIF_TAG_GPS_ALTITUDE_REF, (ExifFormat)EXIF_FORMAT_BYTE, sizeof(uint8_t), 1);
        entry->data[0] = 0; /**< 0 for above sea level */
        
        
        // dumping all exif data
        
        entry = create_or_update_tag(exif, EXIF_IFD_EXIF, (ExifTag)EXIF_TAG_FOCAL_LENGTH, (ExifFormat)EXIF_FORMAT_RATIONAL, sizeof(ExifRational), 1);
        ExifRational focal_len_r = {static_cast<ExifLong>(9.99 * 1000000), 1000000};
        exif_set_rational(entry->data, EXIF_BYTE_ORDER_MOTOROLA, focal_len_r);
        
        entry = create_or_update_tag(exif, EXIF_IFD_EXIF, (ExifTag)EXIF_TAG_FNUMBER, (ExifFormat)EXIF_FORMAT_RATIONAL, sizeof(ExifRational), 1);
        ExifRational f_number_r = {static_cast<ExifLong>(13.6 * 1000000), 1000000};
        exif_set_rational(entry->data, EXIF_BYTE_ORDER_MOTOROLA, f_number_r);
        
        
        entry = create_or_update_tag(exif, EXIF_IFD_EXIF, (ExifTag)EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM, (ExifFormat)EXIF_FORMAT_SHORT, sizeof(ExifShort), 1);
        ExifShort f_35_mm_r = 17;
        exif_set_short(entry->data, EXIF_BYTE_ORDER_MOTOROLA, f_35_mm_r);
        
        exif_data_save_data(exif, &exif_data, &exif_data_len);
        
        //printf("Exif data after mods\n");
        //exif_data_dump(exif);
        //printf("End Exif data after mods\n");
    
        assert(exif_data != NULL);
    #endif
    
        meta.magic_number = CAMERA_MAGIC_NUMBER;
        meta.width        = snap_width;
        meta.height       = snap_height;
        meta.format       = IMAGE_FORMAT_JPG;
        meta.size_bytes   = extractJpgSize;
        pipe_server_write_camera_frame(snapshotPipe, meta, &src_data[start_index]);
    
        // now, if there is a filename in the queue, write it too
        if(snapshotQueue.size() != 0){
            char *filename = snapshotQueue.front();
            snapshotQueue.pop();
    
            M_PRINT("Camera: %s writing snapshot to :\"%s\"\n", name, filename);
            //WriteSnapshot(bufferBlockInfo, snap_halfmt, filename);
    
            FILE* file_descriptor = fopen(filename, "wb");
            if(! file_descriptor){
    
                //Check to see if we were just missing parent directories
                CreateParentDirs(filename);
    
                file_descriptor = fopen(filename, "wb");
    
                if(! file_descriptor){
                    M_ERROR("failed to open file descriptor for snapshot save to: %s\n", filename);
                    return;
                }
            }
    
    #ifndef APQ8096
            
            // first write the beginning of jpeg and stop where the previous exif APP1 header started
            // this will include the FFD8 marker
            printf("Start: 0, end:%lu\n", prev_exif_block_start_idx);
            if (fwrite(src_data, prev_exif_block_start_idx, 1, file_descriptor) != 1) {
                fprintf(stderr, "Error writing to file with jpeg %s\n", filename);
            }
            
            if (fwrite(exif_header, exif_header_len, 1, file_descriptor) != 1) {
               fprintf(stderr, "Error writing to file inin exif header %s\n", filename);
            }
            if (fputc((exif_data_len+2) >> 8, file_descriptor) < 0) {
               fprintf(stderr, "Error writing to file in big endian order %s\n", filename);
            }
            if (fputc((exif_data_len+2) & 0xff, file_descriptor) < 0) {
               fprintf(stderr, "Error writing to file with fputc %s\n", filename);
            }
            if (fwrite(exif_data, exif_data_len, 1, file_descriptor) != 1) {
               fprintf(stderr, "Error writing to file with data block %s\n", filename);
            }
            
            // next write from the last bits of the prev APP1 block
            size_t jpeg_start_idx = prev_exif_block_start_idx + prev_exif_block_size;
            size_t jpeg_size = extractJpgSize - prev_exif_block_size;
            
            //size_t jpeg_start_idx = prev_exif_block_start_idx + prev_exif_block_size + (exif_data_len+2+exif_header_len);
            //size_t jpeg_size = extractJpgSize - prev_exif_block_size + (exif_data_len+2+exif_header_len);
            
            printf("Start: %lu, end:%lu\n", jpeg_start_idx, jpeg_size);
            if (fwrite(src_data + jpeg_start_idx, jpeg_size, 1, file_descriptor) != 1) {
                fprintf(stderr, "Error writing to file with jpeg %s\n", filename);
            }
            
            free(exif_data);
            exif_data_unref(exif);
    
    VOXL SDK

  • Stereo camera calibration not working during extrinsics
    A AndriiHlyvko

    Ok. I figured out the problem. The problem was my calibration chessboard. I taped the pattern to a cardboard box which resulted in some warping of the pattern. After I glued the pattern onto a flat hard surface the calibration worked.

    Ask your questions right here!
  • Login

  • Login or register to search.
  • First post
    Last post
0
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups