Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
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 02 Sep 2014I 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 02 Sep 2014http://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 02 Sep 20149 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 23 Dec 20149 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