Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12606 Discussions

Seeking Guidance on Implementing Sobel Edge Detection for BMP Images on DE0 Experiment Board with SD

CK1143
Beginner
1,115 Views

"I'm looking to implement software and hardware co-design using the DE0 experiment board. My goal is to read a BMP file from an SD card, perform Sobel edge detection, and then save the result back to the SD card. VGA display is not necessary. Currently, I can only manage reading and writing text files. Any suggestions on how to approach this? My BMP images are 800x480 with a 24-bit depth, and the SD card has a capacity of 128MB."

Labels (1)
0 Kudos
10 Replies
EBERLAZARE_I_Intel
1,041 Views

Hi,


For your particular board, we recommend that you seek support directly from Terasic. There are also resources for your board:

https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=56&No=364&PartNo=4#contents


I found this regarding image processing, could be similar to what you trying to achieve? Please contact Terasic directly for further support on this.

https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=&No=657


0 Kudos
EBERLAZARE_I_Intel
1,007 Views

Hi,


Do you have any further questions?


0 Kudos
CK1143
Beginner
991 Views

"I am currently using Python to convert images to text, and in Eclipse, I am able to perform Sobel operations on the text data. I have successfully converted the results back into images using Python for validation. However, I am facing an issue on how to save the Sobel-processed results back to the SD card.

The input image is 100x100, resulting in 10,000 data points. I have tried writing the data back to the SD card from the Nios console, but I can only successfully save approximately 752 records. After that, the data becomes corrupted. How can I overcome this issue?"

"And there are also some errors in the values. For example, the 102nd data point should be 171, but it is recorded as 255."

Nios ii console

CK1143_0-1704170934693.png

txt file

CK1143_1-1704171007006.png

My source code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <altera_up_sd_card_avalon_interface.h>

#define WIDTH 100
#define HEIGHT 100

// 3x3 Sobel operators for gradient calculation
int sobel_x[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
int sobel_y[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};

void applySobel(short int* imageData, unsigned char* resultData) {
    memset(resultData, 0, WIDTH * HEIGHT);

    for (int y = 1; y < HEIGHT - 1; y++) {
        for (int x = 1; x < WIDTH - 1; x++) {
            int gx = 0, gy = 0;

            // Convolution with Sobel operators
            for (int i = -1; i <= 1; i++) {
                for (int j = -1; j <= 1; j++) {
                    int pixelValue = imageData[(y + i) * WIDTH + (x + j)];
                    gx += sobel_x[i + 1][j + 1] * pixelValue;
                    gy += sobel_y[i + 1][j + 1] * pixelValue;
                }
            }

            // Calculate gradient magnitude
            int magnitude = (int)sqrt((double)(gx * gx + gy * gy));

            // Clamp magnitude to 0-255
            magnitude = (magnitude > 255) ? 255 : ((magnitude < 0) ? 0 : magnitude);

            resultData[y * WIDTH + x] = (unsigned char)magnitude;
        }
    }
}

int main() {
    short int sd_fileh;
    alt_up_sd_card_dev *sd_card_dev = alt_up_sd_card_open_dev(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_NAME);

    if (sd_card_dev != 0 && alt_up_sd_card_is_Present() && alt_up_sd_card_is_FAT16()) {
        sd_fileh = alt_up_sd_card_fopen("test8.txt", false);

        if (sd_fileh >= 0) {
            short int imageData[WIDTH * HEIGHT];
            unsigned char resultData[WIDTH * HEIGHT];

            printf("Reading data from test8.txt:\n");

            // Read image data into the array
            for (int i = 0; i < WIDTH * HEIGHT; i++) {
                char buffer[10]; 
                int j;
                for (j = 0; j < 4; j++) {
                    buffer[j] = alt_up_sd_card_read(sd_fileh);
                    if (buffer[j] == -1 || buffer[j] == '\n') {
                        break; 
                    }
                }
                if (j == 0) {
                    break; 
                }
                // Null-terminate the buffer
                buffer[j] = '\0';
                // Print the value read from the file
                printf("%d\n", atoi(buffer));
                imageData[i] = atoi(buffer);
            }

            // Apply Sobel operator to the image data
            applySobel(imageData, resultData);

            // Print the Sobel operation result
            printf("Sobel operation result:\n");
            for (int i = 0; i < WIDTH * HEIGHT; i++) {
                printf("%d\n", resultData[i]);
            }

            // Close the file
            alt_up_sd_card_fclose(sd_fileh);
        } else {
            printf("Problem opening file. Error %i\n", sd_fileh);
        }
    } else {
        printf("SD card not available or not in FAT16 format\n");
    }

    return 0;
}

 

0 Kudos
EBERLAZARE_I_Intel
947 Views

Hi,


I need some time to check into those codes, anyway where did you get this code? Is it your own? Or have you work with this code working previously?


We do have an old example "edge_detection", but I am still need some time to find the example:

https://www.intel.com/content/dam/support/jp/ja/programmable/support-resources/bulk-container/pdfs/literature/an/an377.pdf


0 Kudos
CK1143
Beginner
917 Views

Hi,

I first conducted practical tests on SD card read/write functionality using official Altera documentation(.pdf). Following that, I incorporated the Sobel filter and proceeded to modify the code.

I may have errors in the code I provided earlier, and I will make corrections.

This time, I will attach the results of the Sobel operation. I used Python to convert the text file to PNG for observation. Since I haven't been able to successfully write back to the SD card yet, I manually copied the results from the Nios II Console.

Original:

CK1143_4-1704556363775.png

 

I have included the code for writing back to the SD card.

CK1143_0-1704555710922.png

result image:

CK1143_3-1704556235684.png

 

no writing back to the SD card.

CK1143_1-1704555849251.png

result image:

CK1143_2-1704556209705.png

It's intriguing that after adding the code to write back to the SD card, the Sobel results differ. Removing that part seems to restore the original Sobel outcomes. Currently, I am unable to resolve the issue of not being able to write all Sobel results to the SD card at once, managing to successfully write back only 769 sets of data.

The Sobel results seem to be relatively consistent, with no apparent differences.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <altera_up_sd_card_avalon_interface.h>

#define WIDTH 100
#define HEIGHT 100

// 3x3 Sobel operators for gradient calculation
int sobel_x[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
int sobel_y[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};

void applySobel(short int* imageData, unsigned char* resultData) {
    memset(resultData, 0, WIDTH * HEIGHT);

    for (int y = 1; y < HEIGHT - 1; y++) {
        for (int x = 1; x < WIDTH - 1; x++) {
            int gx = 0, gy = 0;

            // Convolution with Sobel operators
            for (int i = -1; i <= 1; i++) {
                for (int j = -1; j <= 1; j++) {
                    int pixelValue = imageData[(y + i) * WIDTH + (x + j)];
                    gx += sobel_x[i + 1][j + 1] * pixelValue;
                    gy += sobel_y[i + 1][j + 1] * pixelValue;
                }
            }

            // Calculate gradient magnitude
            int magnitude = (int)sqrt((double)(gx * gx + gy * gy));

            // Clamp magnitude to 0-255
            magnitude = (magnitude > 255) ? 255 : ((magnitude < 0) ? 0 : magnitude);

            resultData[y * WIDTH + x] = (unsigned char)magnitude;
        }
    }
}

int main() {
    short int sd_fileh,sd_fileh2;
    alt_up_sd_card_dev *sd_card_dev = alt_up_sd_card_open_dev(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_NAME);

    if (sd_card_dev != 0 && alt_up_sd_card_is_Present() && alt_up_sd_card_is_FAT16()) {
        sd_fileh = alt_up_sd_card_fopen("test8.txt", false);

        if (sd_fileh >= 0) {
            short int imageData[WIDTH * HEIGHT];
            unsigned char resultData[WIDTH * HEIGHT];

            printf("Reading data from test8.txt:\n");

            // Read image data into the array
            for (int i = 0; i < WIDTH * HEIGHT; i++) {
                char buffer[10];
                int j;
                for (j = 0; j < 4; j++) {  // 根據你的像素值調整大小
                	char currentChar = alt_up_sd_card_read(sd_fileh);
                    if (currentChar == -1 || currentChar == '\n') {
                    	break; // 到達檔案結尾或換行字元
                    }
                    buffer[j] = currentChar;
                }
                if (j == 0) {
                    break;
                }
                buffer[j] = '\0';
                printf("%s\n", buffer);
                imageData[i] = atoi(buffer);
            }

            // Apply Sobel operator to the image data
            applySobel(imageData, resultData);

            // Print the Sobel operation result
            printf("Sobel operation result:\n");
            for (int i = 0; i < WIDTH * HEIGHT; i++) {
                printf("%d\n", resultData[i]);

            }
            // Close the original file
            alt_up_sd_card_fclose(sd_fileh);

//            // Create and write the result to test11.txt
//            sd_fileh2 = alt_up_sd_card_fopen("test11.txt", true);
//            if (sd_fileh2 >= 0) {
//                for (int i = 0; i < WIDTH * HEIGHT; i++) {
//                    char buffer[10];
//                    sprintf(buffer, "%d\n", resultData[i]);
//                    alt_up_sd_card_write(sd_fileh2, buffer);
//                }
//                alt_up_sd_card_fclose(sd_fileh2);
//                printf("Sobel result written to test11.txt\n");
//            } else {
//                printf("Problem opening or writing to file. Error %i\n", sd_fileh);
//            }
//
//            // Close the original file
//            alt_up_sd_card_fclose(sd_fileh2);

        } else {
            printf("Problem opening file. Error %i\n", sd_fileh);
        }
    } else {
        printf("SD card not available or not in FAT16 format\n");
    }

    return 0;
}
0 Kudos
CK1143
Beginner
864 Views

I have identified the issue with the different results in Sobel. I found that the lines of code 'char buffer[10];' and 'sprintf(buffer, "%d\n", resultData[i]);' are the main culprits.

CK1143_0-1704771794612.png

I have made modifications using an alternative approach. However, there is still a major issue at hand.

How can I write the results of Sobel back to the SD card? I've noticed on the Intel official website that on December 4, 2014, someone inquired about the issue of "SD card HAL driver cannot write large files correctly." When attempting to open files larger than approximately 4K, an error message appears stating, "The file or directory .... is corrupted and unreadable. Please run the Chkdsk utility."

https://community.intel.com/t5/Intel-FPGA-University-Program/SD-card-HAL-driver-cannot-write-large-files-correctly/td-p/156328 

So, currently, I am unable to resolve the issue of saving Sobel results as a text file back to the SD card.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <altera_up_sd_card_avalon_interface.h>

#define WIDTH 100
#define HEIGHT 100

// 3x3 Sobel operators for gradient calculation
int sobel_x[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
int sobel_y[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};

void applySobel(short int* imageData, unsigned char* resultData) {
    memset(resultData, 0, WIDTH * HEIGHT);

    for (int y = 1; y < HEIGHT - 1; y++) {
        for (int x = 1; x < WIDTH - 1; x++) {
            int gx = 0, gy = 0;

            // Convolution with Sobel operators
            for (int i = -1; i <= 1; i++) {
                for (int j = -1; j <= 1; j++) {
                    int pixelValue = imageData[(y + i) * WIDTH + (x + j)];
                    gx += sobel_x[i + 1][j + 1] * pixelValue;
                    gy += sobel_y[i + 1][j + 1] * pixelValue;
                }
            }

            // Calculate gradient magnitude
            int magnitude = (int)sqrt((double)(gx * gx + gy * gy));

            // Clamp magnitude to 0-255
            magnitude = (magnitude > 255) ? 255 : ((magnitude < 0) ? 0 : magnitude);

            resultData[y * WIDTH + x] = (unsigned char)magnitude;
        }
    }
}

int main() {
    short int sd_fileh,sd_fileh2;
    alt_up_sd_card_dev *sd_card_dev = alt_up_sd_card_open_dev(ALTERA_UP_SD_CARD_AVALON_INTERFACE_0_NAME);

    if (sd_card_dev != 0 && alt_up_sd_card_is_Present() && alt_up_sd_card_is_FAT16()) {
        sd_fileh = alt_up_sd_card_fopen("test8.txt", false);

        if (sd_fileh >= 0) {
            short int imageData[WIDTH * HEIGHT];
            unsigned char resultData[WIDTH * HEIGHT];

            printf("Reading data from test8.txt:\n");

            // Read image data into the array
            for (int i = 0; i < WIDTH * HEIGHT; i++) {
                char buffer[10];
                int j;
                for (j = 0; j < 4; j++) {  // 根據你的像素值調整大小
                	char currentChar = alt_up_sd_card_read(sd_fileh);
                    if (currentChar == -1 || currentChar == '\n') {
                    	break; // 到達檔案結尾或換行字元
                    }
                    buffer[j] = currentChar;
                }
                if (j == 0) {
                    break;
                }
                buffer[j] = '\0';
                printf("%s\n", buffer);
                imageData[i] = atoi(buffer);
            }

            // Apply Sobel operator to the image data
            applySobel(imageData, resultData);

            // Print the Sobel operation result
            printf("Sobel operation result:\n");
            for (int i = 0; i < WIDTH * HEIGHT; i++) {
                printf("%d\n", resultData[i]);

            }
            // Close the original file
            alt_up_sd_card_fclose(sd_fileh);


            // Create and write the result to test11.txt
            sd_fileh2 = alt_up_sd_card_fopen("test11.txt", true);
            if (sd_fileh2 >= 0) {
                for (int i = 0; i < WIDTH * HEIGHT; i++) {
                    // Directly write the resultData[i] to the file with a newline character
                    alt_up_sd_card_write(sd_fileh2, resultData[i]);
                    alt_up_sd_card_write(sd_fileh2, '\n');
                }

                // Close the new file after writing is complete
                alt_up_sd_card_fclose(sd_fileh2);
                printf("Sobel result written to test11.txt\n");
            } else {
                printf("Problem opening or writing to file. Error %i\n", sd_fileh);
            }


        } else {
            printf("Problem opening file. Error %i\n", sd_fileh);
        }
    } else {
        printf("SD card not available or not in FAT16 format\n");
    }

    return 0;
}

 

0 Kudos
EBERLAZARE_I_Intel
768 Views

Hi,


So the latest issue is to save this back to the SD card, let me check this on my side and get back to you.


0 Kudos
EBERLAZARE_I_Intel
721 Views

Hi,


I am still working on this, in the mean time can you check if you could implement below example:

How to mount text file using Altera Nios II Processor (youtube.com)


0 Kudos
EBERLAZARE_I_Intel
696 Views

Hi,


Could you check my previous post?


0 Kudos
EBERLAZARE_I_Intel
645 Views

Hi,


You can also check:

https://ftp.intel.com/Public/Pub/fpgaup/pub/Intel_Material/18.1/University_Program_IP_Cores/Memory/SD_Card_Interface_for_SoPC_Builder.pdf


If you have a new question, Please login to ‘https://supporttickets.intel.com’, view details of the desire request, and post a feed/response within the next 15 days to allow me to continue to support you. After 15 days, this thread will be transitioned to community support. The community users will be able to help you on your follow-up questions.



p/s: If any answer from the community or Intel Support are helpful, please feel free to give best answer or rate 4/5 survey.



0 Kudos
Reply