在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Arduino上的JPEG解碼教程

絕代雙驕 ? 來(lái)源:DevicePlus ? 作者:DevicePlus ? 2023-03-10 17:37 ? 次閱讀

這篇文章來(lái)源于DevicePlus.com英語(yǔ)網(wǎng)站的翻譯稿。

大多數(shù)人聽(tīng)到“JPEG解碼”時(shí),通常會(huì)覺(jué)得這是很困難的事,需要很強(qiáng)的處理能力以及復(fù)雜的數(shù)學(xué)運(yùn)算,并認(rèn)為在相對(duì)便宜且速度較慢的8位處理器平臺(tái)(比如Arduino)上是不可能實(shí)現(xiàn)的,或者說(shuō)至少是不切實(shí)際的。在本文中,我們將學(xué)習(xí)如何使用基于Arduino控制的相機(jī)拍攝JPEG照片,以及如何將照片轉(zhuǎn)換成像素點(diǎn)矩陣,并將所有像素通過(guò)串行端口傳輸?shù)轿覀兊腜C端或者任何我們想要的平臺(tái)上!

硬件

? Arduino Mega

? VC0706 串口攝像頭

? 帶SPI接口SD卡模塊

軟件

? Arduino IDE

? Processing (3.3.2 或更高版本)

? Adafruit VC0706 庫(kù) (可從 GitHub上獲取)

? Bodmer 的 JPEGDecoder 庫(kù) (同樣可從 GitHub上獲取)

雖然說(shuō)上面描述的內(nèi)容是完全可以實(shí)現(xiàn)的,但是仍然有必要解釋一下為什么我們?cè)诮獯aJPEG照片時(shí)會(huì)遇到麻煩。畢竟,在上面的硬件要求中列有一個(gè)SD模塊,您會(huì)問(wèn):“我們直接把照片以photo.jpeg 的格式存儲(chǔ)到SD卡里不就行了嗎?”當(dāng)然,這確實(shí)是整個(gè)過(guò)程中的重要一步,但是現(xiàn)在請(qǐng)從不同的角度來(lái)考慮這個(gè)問(wèn)題:如果我們想通過(guò)速度慢、有些不穩(wěn)定的連接來(lái)發(fā)送照片怎么辦?如果我們只是把JPEG照片分割成不同的包并通過(guò)慢速連接發(fā)送,那么就有部分?jǐn)?shù)據(jù)損壞或丟失的風(fēng)險(xiǎn)。發(fā)生這種情況時(shí),我們很可能無(wú)法用損壞的數(shù)據(jù)還原原始數(shù)據(jù)。

但是,當(dāng)我們將JPEG解碼為位圖,然后發(fā)送實(shí)際像素時(shí),不會(huì)有任何風(fēng)險(xiǎn)。如果某些數(shù)據(jù)在傳輸?shù)倪^(guò)程中損壞或丟失,我們?nèi)匀豢梢垣@取整張圖像,只有數(shù)據(jù)損壞的地方會(huì)出現(xiàn)失色,錯(cuò)位或像素丟失的情況。當(dāng)然,它與我們的原始圖像并不相同,但是仍然包含了大多數(shù)原始信息,并且仍然是“可讀的”。既然已經(jīng)知道了為什么要這樣做,接下來(lái)讓我們看一下如何實(shí)施這種方法。

拍攝照片

在開(kāi)始解碼JPEG照片之前,首先我們需要拍攝照片。我們最終的目標(biāo)是拍攝一張照片,將照片存儲(chǔ)到SD卡中,然后發(fā)送到某個(gè)地方。那我們按照這個(gè)思路先從一個(gè)簡(jiǎn)單的設(shè)置開(kāi)始吧。

poYBAGPzDr-AKi81AAN2hyVZz8E015.jpg

圖1:可以使用Arduino拍攝和存儲(chǔ)照片的設(shè)置

因?yàn)槲覀冃枰罅康?a href="http://www.xsypw.cn/tags/ram/" target="_blank">RAM來(lái)對(duì)照片進(jìn)行解碼,所以我們將使用Arduino Mega。此外,Mega上還有一個(gè)額外的有利設(shè)計(jì):有四個(gè)單獨(dú)的硬件串行端口,這樣我們就可以使用Serial1端口與相機(jī)進(jìn)行通信,并使用Serial端口與PC進(jìn)行通信。

您可能已經(jīng)注意到了,相機(jī)RX線(xiàn)上有一個(gè)簡(jiǎn)單的電阻分壓器。這是因?yàn)閂C0706芯片的邏輯電平為3.3V(即使電源電壓為5V),但Arduino Mega的邏輯電平為5V。所以在這里有個(gè)善意忠告:當(dāng)將5V的Arduino和3.3V模塊進(jìn)行接合時(shí),在RX線(xiàn)上始終至少使用一個(gè)分壓器。這比換一個(gè)新的模塊要快得多。SD卡讀卡器通過(guò)SPI接口直接連接。

既然硬件已經(jīng)設(shè)置好了,那我們就需要開(kāi)始解決代碼部分了。標(biāo)準(zhǔn)Arduino IDE安裝已經(jīng)包含了用于SD卡的庫(kù),因此我們從列表中對(duì)SD卡進(jìn)行查看即可。

我們需要控制的另一個(gè)設(shè)備是VC0706攝像頭。控制過(guò)程相對(duì)簡(jiǎn)單,我們只需要使用串行線(xiàn)發(fā)送一些指令,然后通過(guò)同一條線(xiàn)接收J(rèn)PEG照片即可。我們可以編寫(xiě)一個(gè)庫(kù)來(lái)執(zhí)行此操作,但是因?yàn)檫@一步我們不需要考慮整體草圖的大小,所以我們將使用Adafruit開(kāi)發(fā)的一個(gè)VC0706庫(kù)。為了拍攝照片并保存到SD卡上,我們將使用以下代碼,代碼是該庫(kù)隨附的經(jīng)過(guò)輕微修改的Snapshot示例。

// Include all the libraries
#include 
#include 
#include 

// Define Slave Select pin
#define SD_CS  53

// Create an instance of Adafruit_VC0706 class
// We will use Serial1 for communication with the camera
Adafruit_VC0706 cam = Adafruit_VC0706(&Serial1);

void setup() {
  // Begin Serial port for communication with PC
  Serial.begin(115200);

  // Start the SD
  if(!SD.begin(SD_CS)) {
    // If the SD can't be started, loop forever
    Serial.println("SD failed or not present!");
    while(1);
  }

  // Start the camera
  if(!cam.begin()) {
    // If the camera can't be started, loop forever
    Serial.println("Camera failed or not present!");
    while(1);
  }

  // Set the image size to 640x480
  cam.setImageSize(VC0706_640x480);
}

void loop() {
  Serial.print("Taking picture in 3 seconds ... ");
  delay(3000);
  
  // Take a picture
  if(cam.takePicture()) {
    Serial.println("done!");
  } else {
    Serial.println("failed!");
  }

  // Create a name for the new file in the format IMAGExy.JPG
  char filename[13];
  strcpy(filename, "IMAGE00.JPG");
  for(int i = 0; i < 100; i++) {
    filename[5] = '0' + i/10;
    filename[6] = '0' + i%10;
    if(!SD.exists(filename)) {
      break;
    }
  }

  // Create a file with the name we created above and open it
  File imgFile = SD.open(filename, FILE_WRITE);

  // Get the size of the image
  uint16_t jpglen = cam.frameLength();
  Serial.print("Writing ");
  Serial.print(jpglen, DEC);
  Serial.print(" bytes into ");
  Serial.print(filename);
  Serial.print(" ... ");

  // Read all the image data
  while(jpglen > 0) {
    // Load the JPEG-encoded image data from the camera into a buffer
    uint8_t *buff;
    uint8_t bytesToRead = min(32, jpglen);
    buff = cam.readPicture(bytesToRead);

    // Write the image data to the file
    imgFile.write(buff, bytesToRead);
    jpglen -= bytesToRead;
  }

  // Safely close the file
  imgFile.close();
  
  Serial.println("done!");
  delay(3000);
}

現(xiàn)在,Arduino將每10秒左右拍攝一張照片,直到SD卡上的空間用完為止。但是,由于照片通常約為48kB,并且我目前使用的是2GB的SD卡,因此足夠容納超過(guò)43000張的照片。理論上來(lái)說(shuō)我們不需要那么多的照片。但是既然已經(jīng)拍攝了一些照片,我們現(xiàn)在可以繼續(xù)進(jìn)行下一個(gè)有趣環(huán)節(jié)了:將它們從JPEG壓縮后的難以管理的雜亂數(shù)據(jù)變成簡(jiǎn)單的像素陣列!

解碼和發(fā)送照片

在開(kāi)始解碼前,讓我們快速地看一下圖片數(shù)據(jù)在JPEG文件中究竟是如何存儲(chǔ)的。如果您對(duì)這部分不太感興趣,可以跳過(guò)下面三段內(nèi)容。如果您確切地對(duì)圖形和壓縮方面的知識(shí)了解一二(不像我這樣),您也可以跳過(guò)這一部分。以下內(nèi)容進(jìn)行了一定程度的簡(jiǎn)化。

對(duì)任何類(lèi)型的圖片數(shù)據(jù)進(jìn)行存儲(chǔ)時(shí),有兩種基本方法:無(wú)損和有損壓縮。兩者的區(qū)別很明顯:當(dāng)使用無(wú)損壓縮(例如PNG)對(duì)圖像進(jìn)行編碼時(shí),處理之后圖像的每個(gè)像素都與開(kāi)始時(shí)完全相同。這非常適合于諸如計(jì)算機(jī)圖形學(xué)之類(lèi)的工作,但是不幸的是,這是以增加文件大小為代價(jià)的。另一方面,對(duì)于像JPEG這樣的有損壓縮,我們丟失了一些細(xì)節(jié),但是生成的文件大小要小得多。

JPEG壓縮方式在理解上可能會(huì)有點(diǎn)困難,因?yàn)闀?huì)涉及到一些“離散余弦變換”,不過(guò)主要原理實(shí)際上是非常簡(jiǎn)單的。首先,將圖片從RGB顏色空間轉(zhuǎn)換為YCbCr。我們都知道RGB顏色空間—它存儲(chǔ)了紅色(R)、綠色(G)和藍(lán)色(B)的顏色值。YCbCr有很大的不同—它使用亮度(Y—基本是原始圖像的灰度圖),藍(lán)色差分量(Cb—圖片中的“藍(lán)色”)和紅色差分量(Cr—圖片中的“紅色”)。

poYBAGPzDsWAUE6wAAPEyW8spAw375.jpg

圖2:JPEG照片以及其分離出的色差分量。左上角為原始圖像,左下角為Y分量,右上角為Cb分量,右下角為Cr分量

JPEG減小文件大小的方法實(shí)際上與人眼處理顏色的方式密切相關(guān)。看一下上圖中的Y、Cb和Cr分量圖。哪一個(gè)看起來(lái)更像是原始圖片?是的,灰度圖!這是因?yàn)槿搜蹖?duì)亮度的敏感度要比對(duì)其它兩個(gè)分量的敏感度高得多。JPEG壓縮就非常聰明地利用了這一點(diǎn),在保留原始Y分量的同時(shí)減少Cb和Cr分量中的信息量。如此一來(lái),生成的圖片就比原始文件小得多,并且由于大多數(shù)壓縮信息都位于人眼不太敏感的分量中,因此與未壓縮的圖片相比,您幾乎看不到壓縮圖片的區(qū)別。

現(xiàn)在,讓我們開(kāi)始運(yùn)行真正實(shí)現(xiàn)將JPEG轉(zhuǎn)換為像素陣列的代碼吧。幸運(yùn)的是,有一個(gè)庫(kù)可以做到這一點(diǎn)—Bodmer的JPEGDecoder(可在GitHub上獲得),該庫(kù)基于Rich Geldreich(也可在GitHub)上獲取)提供的出色的picojpeg庫(kù)。雖然最初編寫(xiě)JPEGDecoder的目的是在TFT顯示器上顯示圖像,但是將其進(jìn)行一些細(xì)微調(diào)整后就可以用于我們的工作了。

該庫(kù)的使用非常簡(jiǎn)單:我們輸入JPEG文件,然后該庫(kù)就會(huì)開(kāi)始產(chǎn)生像素陣列—所謂的最小編碼單位,或簡(jiǎn)稱(chēng)為MCU。MCU是一個(gè)16×8的像素塊。庫(kù)中的函數(shù)將以16位顏色值的形式返回每個(gè)像素點(diǎn)的顏色值。高5位是紅色值,中6位是綠色值,低5位是藍(lán)色值。現(xiàn)在,我們可以通過(guò)任何通信通道來(lái)發(fā)送這些值。我將使用串行端口,以便之后可以更容易地接收數(shù)據(jù)。下面的Arduino草圖對(duì)一張圖像進(jìn)行了解碼,然后發(fā)送了MCU中每個(gè)像素點(diǎn)的16位RGB值,并對(duì)圖像文件中的所有MCU重復(fù)該操作。

// Include the library
#include 

// Define Slave Select pin
#define SD_CS  53

void setup() {
  // Set pin 13 to output, otherwise SPI might hang
  pinMode(13, OUTPUT);

  // Begin Serial port for communication with PC
  Serial.begin(115200);

  // Start the SD
  if(!SD.begin(SD_CS)) {
    // If the SD can't be started, loop forever
    Serial.println("SD failed or not present!");
    while(1);
  }

  // Open the root directory
  File root = SD.open("/");
  
  // Wait for the PC to signal
  while(!Serial.available());

  // Send all files on the SD card
  while(true) {
    // Open the next file
    File jpgFile = root.openNextFile();

    // We have sent all files
    if(!jpgFile) {
      break;
    }

    // Decode the JPEG file
    JpegDec.decodeSdFile(jpgFile);

    // Create a buffer for the packet
    char dataBuff[240];

    // Fill the buffer with zeros
    initBuff(dataBuff);

    // Create a header packet with info about the image
    String header = "$ITHDR,";
    header += JpegDec.width;
    header += ",";
    header += JpegDec.height;
    header += ",";
    header += JpegDec.MCUSPerRow;
    header += ",";
    header += JpegDec.MCUSPerCol;
    header += ",";
    header += jpgFile.name();
    header += ",";
    header.toCharArray(dataBuff, 240);

    // Send the header packet
    for(int j=0; j<240; j++) {
      Serial.write(dataBuff[j]);
    }

    // Pointer to the current pixel
    uint16_t *pImg;

    // Color of the current pixel
    uint16_t color;

    // Create a data packet with the actual pixel colors
    strcpy(dataBuff, "$ITDAT");
    uint8_t i = 6;

    // Repeat for all MCUs in the image
    while(JpegDec.read()) {
      // Save pointer the current pixel
      pImg = JpegDec.pImage;

      // Get the coordinates of the MCU we are currently processing
      int mcuXCoord = JpegDec.MCUx;
      int mcuYCoord = JpegDec.MCUy;

      // Get the number of pixels in the current MCU
      uint32_t mcuPixels = JpegDec.MCUWidth * JpegDec.MCUHeight;

      // Repeat for all pixels in the current MCU
      while(mcuPixels--) {
        // Read the color of the pixel as 16-bit integer
        color = *pImg++;
        
        // Split it into two 8-bit integers
        dataBuff[i] = color >> 8;
        dataBuff[i+1] = color;
        i += 2;

        // If the packet is full, send it
        if(i == 240) {
          for(int j=0; j<240; j++) {
            Serial.write(dataBuff[j]);
          }
          i = 6;
        }

        // If we reach the end of the image, send a packet
        if((mcuXCoord == JpegDec.MCUSPerRow - 1) && 
          (mcuYCoord == JpegDec.MCUSPerCol - 1) && 
          (mcuPixels == 1)) {
          
          // Send the pixel values
          for(int j=0; j

注釋中已經(jīng)對(duì)大多數(shù)代碼進(jìn)行了解釋?zhuān)俏疫€是需要對(duì)代碼結(jié)構(gòu)中的“包”進(jìn)行一些說(shuō)明。為了使數(shù)據(jù)傳輸更加有序,所有內(nèi)容都以包的形式傳輸,最大長(zhǎng)度為240字節(jié)。包有兩種可能的類(lèi)型:

1.頭包:此包以字符串“$ITHDR”開(kāi)頭,并且包含我們將要發(fā)送的圖片的基本信息:以像素為單位的高度和寬度,行和列前的MCU數(shù)量,最后是原始文件名。對(duì)于我們要發(fā)送的每個(gè)圖像,都會(huì)相應(yīng)發(fā)送一個(gè)頭包。

2.數(shù)據(jù)包:該包以“$ITDAT”開(kāi)頭,并包含所有顏色數(shù)據(jù)。該數(shù)據(jù)包中的每?jī)蓚€(gè)字節(jié)代表一個(gè)16位像素值。

乍一看,包的長(zhǎng)度似乎是隨機(jī)的。但是為什么恰好是240個(gè)字節(jié)?為什么不是256個(gè),使我們可以在每個(gè)包中發(fā)送兩個(gè)MCU呢?這是另一個(gè)我們?nèi)蘸髮?huì)解決的謎團(tuán),但是我們可以保證, 數(shù)字240不會(huì)有任何隨機(jī)性。這里有個(gè)小提示:如果包中有256個(gè)字節(jié)的數(shù)據(jù),我們要在哪里存儲(chǔ)源地址和目標(biāo)地址呢?

現(xiàn)在,我們有了一個(gè)可以解碼和發(fā)送圖片文件的代碼,但是仍然缺少一個(gè)核心功能:目前為止,并沒(méi)有可以響應(yīng)這些數(shù)據(jù)的另一端口。這意味著是時(shí)候再次啟用Processing了!

接收?qǐng)D片

我在Arduino六足機(jī)器人第三部分:遠(yuǎn)程控制中曾介紹過(guò)一些有關(guān)Processing的內(nèi)容,用其編寫(xiě)了一個(gè)應(yīng)用程序,通過(guò)該應(yīng)用程序我們能夠輕松控制六足機(jī)器人。簡(jiǎn)單回顧一下:Processing是一種基于Java的語(yǔ)言,主要用于繪圖工作。因此它非常適用于我們現(xiàn)在要做的像素顯示的工作!該程序就是用Processing實(shí)現(xiàn)的。

// Import the library
import processing.serial.*;

Serial port;

void setup() {
  // Set the default window size to 200 by 200 pixels
  size(200, 200);
  
  // Set the background to grey
  background(#888888);
  
  // Set as high framerate as we can
  frameRate(1000000);
  
  // Start the COM port communication
  // You will have to replace "COM30" with the Arduino COM port number
  port = new Serial(this, "COM30", 115200);
  
  // Read 240 bytes at a time
  port.buffer(240);
}

// String to save the trimmed input
String trimmed;

// Buffer to save data incoming from Serial port
byte[] byteBuffer = new byte[240];

// The coordinate variables
int x, y, mcuX, mcuY;

// A variable to measure how long it takes to receive the image
long startTime;

// A variable to save the current time
long currentTime;

// Flag to signal end of transmission
boolean received = false;

// Flag to signal reception of header packet
boolean headerRead = false;

// The color of the current pixel
int inColor, r, g, b;

// Image information variables
int jpegWidth, jpegHeight, jpegMCUSPerRow, jpegMCUSPerCol, mcuWidth, mcuHeight, mcuPixels;

// This function will be called every time any key is pressed
void keyPressed() {
  // Send something to Arduino to signal the start
  port.write('s');
}

// This function will be called every time the Serial port receives 240 bytes
void serialEvent(Serial port) {
  // Read the data into buffer
  port.readBytes(byteBuffer);
  
  // Make a String out of the buffer
  String inString = new String(byteBuffer);
  
  // Detect the packet type
  if(inString.indexOf("$ITHDR") == 0) {
    // Header packet
    
    // Remove all whitespace characters
    trimmed = inString.trim();
    
    // Split the header by comma
    String[] list = split(trimmed, ',');
    
    // Check for completeness
    if(list.length != 7) {
      println("Incomplete header, terminated");
      while(true);
    } else {
      // Parse the image information
      jpegWidth = Integer.parseInt(list[1]);
      jpegHeight = Integer.parseInt(list[2]);
      jpegMCUSPerRow = Integer.parseInt(list[3]);
      jpegMCUSPerCol = Integer.parseInt(list[4]);
      
      // Print the info to console
      println("Filename: " + list[5]);
      println("Parsed JPEG width: " + jpegWidth);
      println("Parsed JPEG height: " + jpegHeight);
      println("Parsed JPEG MCUs/row: " + jpegMCUSPerRow);
      println("Parsed JPEG MCUs/column: " + jpegMCUSPerCol);
      
      // Start the timer
      startTime = millis();
    }
    
    // Set the window size according to the received information
    surface.setSize(jpegWidth, jpegHeight);
    
    // Get the MCU information
    mcuWidth = jpegWidth / jpegMCUSPerRow;
    mcuHeight = jpegHeight / jpegMCUSPerCol;
    mcuPixels = mcuWidth * mcuHeight;
    
  } else if(inString.indexOf("$ITDAT") == 0) {
    // Data packet
    
    // Repeat for every two bytes received
    for(int i = 6; i < 240; i += 2) {
      // Combine two 8-bit values into a single 16-bit color
      inColor = ((byteBuffer[i] & 0xFF) << 8) | (byteBuffer[i+1] & 0xFF);
      
      // Convert 16-bit color into RGB values
      r = ((inColor & 0xF800) >> 11) * 8;
      g = ((inColor & 0x07E0) >> 5) * 4;
      b = ((inColor & 0x001F) >> 0) * 8;
      
      // Paint the current pixel with that color
      set(x + mcuWidth*mcuX, y + mcuHeight*mcuY, color(r, g, b));
      
      // Move onto the next pixel
      x++;
      
      if(x == mcuWidth) {
        // MCU row is complete, move onto the next one
        x = 0;
        y++;
      }
      
      if(y == mcuHeight) {
        // MCU is complete, move onto the next one
        x = 0;
        y = 0;
        mcuX++;
      }
      
      if(mcuX == jpegMCUSPerRow) {
        // Line of MCUs is complete, move onto the next one
        x = 0;
        y = 0;
        mcuX = 0;
        mcuY++;
      }
      
      if(mcuY == jpegMCUSPerCol) {
        // The entire image is complete
        received = true;
      }
    }
  }
}

void draw() {
  // If we received a full image, start the whole process again
  if(received) {
    
    // Reset coordinates
    x = 0;
    y = 0;
    mcuX = 0;
    mcuY = 0;
    
    // Reset the flag
    received = false;
    
    // Measure how long the whole thing took
    long timeTook = millis() - startTime;
    println("Image receiving took: " + timeTook + " ms");
    println();
  }
}

當(dāng)您在連接Arduino之后運(yùn)行該程序,然后按下鍵盤(pán)上的任意鍵時(shí),您(希望)會(huì)看到暗淡、單一的灰色背景逐漸被最初存儲(chǔ)在SD卡上的圖像所取代。由于替換是逐像素進(jìn)行的,因此整個(gè)過(guò)程具有一種老式撥號(hào)調(diào)制解調(diào)器的加載圖像風(fēng)格!

pYYBAGPzDsmAe9OIAAK-0coq5c8684.jpg

圖3:使用Processing應(yīng)用程序?qū)⒄掌瑥腁rduino加載到PC

雖然我們以相當(dāng)高的波特率(準(zhǔn)確值為115200)運(yùn)行串行端口,接收一張圖像也需要大約60秒。我們可以用它來(lái)計(jì)算實(shí)際的傳輸速度。

原始圖像寬640像素,高480像素,總計(jì)307200像素。每個(gè)像素都由2字節(jié)的顏色值來(lái)表示,總共要傳輸614400個(gè)字節(jié)(即600KB)。那么我們的最終速度約為10kB/s。對(duì)于我們制定的“協(xié)議”來(lái)說(shuō),這并不算很糟糕,不是嗎?此外,它還向您展示了為什么圖像壓縮如此有用。原始JPEG文件只有48kB左右,而解碼后的位圖則需要600kB。如果我們要傳輸JPEG文件,即使使用非常簡(jiǎn)單的“協(xié)議”,也可以在5秒之內(nèi)完成傳輸。當(dāng)然,萬(wàn)一傳輸失敗,我們將可能無(wú)法追回任何數(shù)據(jù)—這種情況現(xiàn)在已經(jīng)不會(huì)發(fā)生了。

結(jié)論

最后,我們證實(shí)了本文開(kāi)頭所說(shuō)的:在Arduino上處理圖像是可能的,并且在某些情況下可能會(huì)更有優(yōu)勢(shì)。現(xiàn)在,我們可以使用串行相機(jī)拍攝照片,對(duì)其進(jìn)行解碼,通過(guò)串行端口發(fā)送,然后在另一端接收了!可以將本文作為您在Arduino上進(jìn)行圖像處理的入門(mén)簡(jiǎn)介。

像往常一樣,有很多方面都可以進(jìn)一步改善。一個(gè)需要添加的主要功能可能是使用AES對(duì)我們的消息進(jìn)行加密,這一點(diǎn)很容易實(shí)現(xiàn)(即使在Arduino上)。在Arduino上,安全性通常會(huì)被忽視,這是很危險(xiǎn)的,因此在下一個(gè)項(xiàng)目中我們可能會(huì)將重點(diǎn)更多地放在安全性上。

感謝您閱讀本文!請(qǐng)繼續(xù)關(guān)注我們的其他有趣項(xiàng)目!也許有些項(xiàng)目將會(huì)使用到我們?cè)诒卷?xiàng)目中所學(xué)到的所有內(nèi)容!

審核編輯黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 解碼
    +關(guān)注

    關(guān)注

    0

    文章

    181

    瀏覽量

    27407
  • JPEG
    +關(guān)注

    關(guān)注

    0

    文章

    66

    瀏覽量

    29973
  • Arduino
    +關(guān)注

    關(guān)注

    188

    文章

    6474

    瀏覽量

    187427
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    【NanoPi NEO2試用體驗(yàn)】libjpeg庫(kù)的使用之jpeg解碼

    使用libjpeg進(jìn)行jpeg解碼需要libjpeg動(dòng)態(tài)鏈接庫(kù)以及l(fā)ibjpeg的頭文件,一篇文章已經(jīng)編譯好了libjpeg庫(kù),進(jìn)行解碼的時(shí)候需要一個(gè)
    發(fā)表于 07-01 10:15

    軟件解碼JPEG怎么實(shí)現(xiàn)?

    地受到各種小型嵌入式產(chǎn)品的青睞。目前嵌入式系統(tǒng)方面對(duì)JPEG圖像軟件解碼較多地應(yīng)用在DSP和多核等高速處理器
    發(fā)表于 08-13 06:02

    JPEG圖像硬件解碼低功耗技術(shù)方案

    JPEG圖像硬件解碼低功耗技術(shù)方案 為了實(shí)現(xiàn)數(shù)據(jù)的實(shí)時(shí)處理和低功耗應(yīng)用,本文提出了一種帶有時(shí)鐘管理機(jī)制的并行、全流水結(jié)構(gòu)的
    發(fā)表于 04-20 11:19 ?1284次閱讀
    <b class='flag-5'>JPEG</b>圖像硬件<b class='flag-5'>解碼</b>低功耗技術(shù)方案

    JPEG圖像解碼方案

    JPEG圖像解碼方案,很好的資料,快來(lái)學(xué)習(xí)吧
    發(fā)表于 02-18 14:16 ?0次下載

    E文JPEG解碼介紹

    E文JPEG解碼介紹,很好的資料,快來(lái)學(xué)習(xí)吧
    發(fā)表于 02-18 14:14 ?0次下載

    JPEG解碼

    JPEG解碼介紹,很好的資料,快來(lái)學(xué)習(xí)吧
    發(fā)表于 02-18 14:24 ?0次下載

    多核處理器構(gòu)架的高速JPEG解碼算法

    多核處理器構(gòu)架的高速JPEG解碼算法,很好的資料,快來(lái)學(xué)習(xí)吧
    發(fā)表于 02-18 13:54 ?0次下載

    基于FPGA的JPEG解碼算法的研究與實(shí)現(xiàn)

    基于FPGA的JPEG解碼算法的研究與實(shí)現(xiàn),很好的資料,快來(lái)學(xué)習(xí)吧
    發(fā)表于 02-18 13:53 ?0次下載

    基于FPGA的JPEG解碼算法的研究與實(shí)現(xiàn)

    基于FPGA的JPEG解碼算法的研究與實(shí)現(xiàn)
    發(fā)表于 08-29 16:05 ?11次下載

    基于FPGA的JPEG實(shí)時(shí)圖像編解碼系統(tǒng)

    基于FPGA的JPEG實(shí)時(shí)圖像編解碼系統(tǒng)
    發(fā)表于 08-29 16:05 ?15次下載

    jpeg格式圖片疊加bmp或png格式水印操作資料下載

    利用libjpeg 解碼jpeg并和bmp疊加,在編碼成jpeg圖片,利用libpng解碼png將png圖片疊加到jpeg圖片
    發(fā)表于 01-20 10:30 ?4次下載

    如何使用FPGA實(shí)現(xiàn)JPEG解碼算法的研究與實(shí)現(xiàn)論文免費(fèi)下載

    可編程門(mén)陣列)設(shè)計(jì)流程的基礎(chǔ),從總體規(guī)劃的角度提出了整個(gè)系統(tǒng)結(jié)構(gòu)的設(shè)計(jì)思想,對(duì)JPEG解碼器各部分算法進(jìn)行了深入的研究,接著對(duì)各個(gè)模塊的設(shè)計(jì)進(jìn)行了詳細(xì)的描述。采用了Verilog硬件描述語(yǔ)言對(duì)
    發(fā)表于 01-29 15:27 ?13次下載
    如何使用FPGA實(shí)現(xiàn)<b class='flag-5'>JPEG</b><b class='flag-5'>解碼</b>算法的研究與實(shí)現(xiàn)論文免費(fèi)下載

    ADV212:JPEG 2000視頻編解碼器數(shù)據(jù)表

    ADV212:JPEG 2000視頻編解碼器數(shù)據(jù)表
    發(fā)表于 05-24 19:43 ?19次下載
    ADV212:<b class='flag-5'>JPEG</b> 2000視頻編<b class='flag-5'>解碼</b>器數(shù)據(jù)表

    下載適用于Blackfin的JPEG解碼器的生產(chǎn)版。

    下載適用于Blackfin的JPEG解碼器的生產(chǎn)版。
    發(fā)表于 06-07 20:34 ?0次下載
    下載適用于Blackfin的<b class='flag-5'>JPEG</b><b class='flag-5'>解碼</b>器的生產(chǎn)版。

    JPEG解碼程序

    JPEG解碼程序分享。
    發(fā)表于 09-28 16:04 ?6次下載
    主站蜘蛛池模板: 高清一区二区三区免费| 亚洲国产精品丝袜在线观看| 天天干夜夜艹| 日韩特黄特色大片免费视频| 日本伊人网| 热久在线| 亚洲一区有码| 美女扒开内裤无遮挡禁18| 九九re| 一级做a爰片久久毛片图片| 伊人久久大香线蕉综合网站| 亚洲人成a在线网站| 色偷偷97| 九九九色| 亚洲精品视频在线看| 全部免费特黄特色大片视频| 成年男人午夜片免费观看| 69女poren16| 成人午夜免费剧场| 五月激情六月丁香| 男男扒开后菊惩罚| 亚洲地址一地址二地址三| 日日艹| 国产欧美网站| 天天干在线观看| 成人午夜影院在线观看| 亚洲综合在线观看一区www| 一级做受毛片免费大片| 日产乱码免费一卡二卡在线| 亚洲福利片| 日韩国产片| 国产一卡二卡≡卡四卡无人 | 啪啪午夜视频| 禁漫画羞羞动漫入口| 8844aa在线毛片| 在线a网站| 欧美性天天影院| bt天堂在线最新版www| 久久观看| 亚洲韩国欧美一区二区三区| 午夜免费福利片观看|