10 years, 3 months ago.

Processing image in LPC1768 mbed microcontroller taken form LinkSprite JPEG Color Camera

I have bought LinkSprite JPEG Color Camera and a LPC1768 mbed microcontroller. By "LinkSprite" camera i can take image in jpeg formate and according to their provided tutorial i can transfer and see these image on desktop.But i want to process these image in "LPC1768 mbed" micro-controller.For example i want to loop through each row and column of that image to match a color. Can anyone tell me how can i receive the whole image into an 2D-array and then loop through the array to match with a color like red . Another problem when i transfer the image the data looks like. ff d8 ff e0 00 10 ...........40 c6 81 90 b9 aa ee 68 19 ff d9. I know that jpeg image starts with ff d9 and ends with ff d9. But how can i identify a pixel among those values and how can i compare a color whether it match with red color???

I have transferred image with these code:

#include "mbed.h"
#include "JPEGCamera.h"

DigitalOut myled1(LED1); //show successful picture was taken 
DigitalOut myled2(LED2); //show end of sequence
DigitalOut myled3(LED3); //show picture take failed
DigitalOut myled4(LED4); //show camera is not ready


int main() {
    JPEGCamera camera(p9, p10); // TX, RX
    LocalFileSystem local("local"); //save images on mbed
    Timer timer;
    timer.start();
    if(camera.setPictureSize(JPEGCamera::SIZE160x120))
    {
      myled1 = 1;
      wait(2.0);
      myled1 = 0; 
      wait(2.0); 
    }
    for (int i = 1; i < 3; i++) {
        if (camera.isReady()) {
            char filename[32];
            sprintf(filename, "/local/pict%03d.jpg", i);
            printf("Picture: %s \n", filename);
            if (camera.takePicture(filename)) {
                while (camera.isProcessing()) {
                    camera.processPicture();
                }
                
                
                myled1 = 1; //show successful picture was taken 
                wait(2.0);
                myled1 = 0;
            } else {
                printf("take picture failed\n");
                myled3 = 1; //show picture take failed
                wait(2.0);
                myled3 = 0;
            }
        } else {
            printf("camera is not ready\n");
            myled4 = 1; //show camera is not ready
            wait(2.0);
            myled4 = 0;
        }
    }
    myled2 = 1; //show end of sequence
    wait(2.0);
    myled2 = 0;
    printf("time = %f\n", timer.read());
}

JPEGCamera.cpp

#include "JPEGCamera.h"
#define min(x, y) ((x) < (y)) ? (x) : (y)


const int RESPONSE_TIMEOUT = 500;
const int DATA_TIMEOUT = 1500;


Serial bt(p13, p14);

JPEGCamera::JPEGCamera(PinName tx, PinName rx) : Serial(tx, rx) {
    baud(115200);
    bt.baud(115200);
    state = READY;
}

bool JPEGCamera::setPictureSize(JPEGCamera::PictureSize size, bool doReset) {
    char buf[5] = {0x56, 0x00, 0x54, 0x01, (char) size};
    int ret = sendReceive(buf, sizeof buf, 5);

    if (ret == 5 && buf[0] == 0x76) {
        if (doReset)
            reset();
        return true;
    } else
        return false;
}

bool JPEGCamera::isReady() {
    return state == READY;
}

bool JPEGCamera::isProcessing() {
    return state == PROCESSING;
}

bool JPEGCamera::takePicture(char *filename) {
    if (state == READY) {
        fp = fopen(filename, "wb");
        if (fp != 0) {
            if (takePicture()) {
                imageSize = getImageSize();
                address = 0;
                state = PROCESSING;
            } else {
                fclose(fp);
                printf("takePicture(%s) failed", filename);
                state = ERROR;
            }
        } else {
            printf("fopen() failed");
            state = ERROR;
        }
    }
    return state != ERROR;
}

bool JPEGCamera::processPicture() {
    if (state == PROCESSING) {
        bt.printf("\n\nNew Image \n\n");
        if (address < imageSize) {
            char data[2048];
            int size = readData(data, min(sizeof(data), imageSize - address), address);
            int ret = fwrite(data, size, 1, fp);
            for (int i=0; i<size; i++) bt.printf("%x ",data[i]);
            if (ret > 0)
                address += size;
            if (ret == 0 || address >= imageSize) {
                stopPictures();
                fclose(fp);
                wait(0.1); // ????
                state = ret > 0 ? READY : ERROR;
            }
        }
    }

    return state == PROCESSING || state == READY;
}

bool JPEGCamera::reset() {
    char buf[4] = {0x56, 0x00, 0x26, 0x00};
    int ret = sendReceive(buf, sizeof buf, 12);
    if (ret == 12 && buf[0] == 0x0D) {
        wait(4.0);
        state = READY;
    } else {
        state = ERROR;
    }
    return state == READY;
}

bool JPEGCamera::takePicture() {
    char buf[5] = {0x56, 0x00, 0x36, 0x01, 0x00};
    int ret = sendReceive(buf, sizeof buf, 5);

    return ret == 5 && buf[0] == 0x76;
}

bool JPEGCamera::stopPictures() {
    char buf[5] = {0x56, 0x00, 0x36, 0x01, 0x03};
    int ret = sendReceive(buf, sizeof buf, 5);

    return ret == 4 && buf[0] == 0x76;
}

int JPEGCamera::getImageSize() {
    char buf[9] = {0x56, 0x00, 0x34, 0x01, 0x00};
    int ret = sendReceive(buf, sizeof buf, 9);

    //The size is in the last 2 characters of the response.
    return (ret == 9 && buf[0] == 0x76) ? (buf[7] << 8 | buf[8]) : 0;
}

int JPEGCamera::readData(char *dataBuf, int size, int address) {
    char buf[16] = {0x56, 0x00, 0x32, 0x0C, 0x00, 0x0A, 0x00, 0x00,
                    address >> 8, address & 255, 0x00, 0x00, size >> 8, size & 255, 0x00, 0x0A
                   };
    int ret = sendReceive(buf, sizeof buf, 5);

    return (ret == 5 && buf[0] == 0x76) ? receive(dataBuf, size, DATA_TIMEOUT) : 0;
}

int JPEGCamera::sendReceive(char *buf, int sendSize, int receiveSize) {
    while (readable()) getc();

    for (int i = 0; i < sendSize; i++) putc(buf[i]);

    return receive(buf, receiveSize, RESPONSE_TIMEOUT);
}

int JPEGCamera::receive(char *buf, int size, int timeout) {
    timer.start();
    timer.reset();

    int i = 0;
    while (i < size && timer.read_ms() < timeout) {
        if (readable())
            buf[i++] = getc();
    }

    return i;
}

3 Answers

10 years, 3 months ago.

I'm afraid its a bit more complicated then finding the pixels you want in those values, Jpeg is a compressed format and to get the raw data you will first need to decompress the file.

There is a related question here: http://mbed.org/questions/352/Any-code-to-uncompress-the-jpg-image/

(editing my answer didn't seem to work)

The lowest setting on that camera is 160x120, assuming rgb format that is 57600 bytes of data, a bit much for the LPC1768 to handle. I think you may have to scan a file stream rather than store the image in memory.

posted by Chris Pepper 02 Sep 2014

I couldn't understand how to decode(use the decoder library,i couldn't find any documentation). What should i do?? i fully jammed with this problem. dont know what to do. plz tell me what should i do.

posted by imon bayazid 02 Sep 2014

http://mbed.org/users/XkLi/code/Lab3/file/c546b51ecf0b/picojpeg The function ReadJpegFromFile appears to be useful, could probably be modified for your needs.

posted by Chris Pepper 02 Sep 2014
9 years, 12 months ago.

Has anyone solved this problem. I m facing it too

If you're wanting to access the pixel data in a JPG, then you hae to use some JPG library to decode the compressed data into an array. Chris Pepper posted a link to picojpeg which is a small JPEG decompression library of some kind. As others have also said, you many not have enough memory to decode the entire image at once, so you would have to modify that library with a callback or something where you can process the data as a stream instead of in-memory all at once.

posted by Dan East 23 Dec 2014
9 years, 10 months ago.

I can read data of image, but I cant open the image, because header of JPEG format is missing, can you help me ? I send data of image using RCTimer

Thanks /media/uploads/dobs/data.png