• 正文
    • oepcv介紹:
    • opencv-python使用:
    • opencv c++使用:
    • 結(jié)語
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

jetson-nano opencv基礎(chǔ)使用

02/03 09:17
283
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

jetson nano前一篇給大家介紹了學(xué)習(xí)的一些思路和資料,今天繼續(xù)給大家分享一篇在jetson nano使用opencv的文章。

OpenCV的全稱是Open Source Computer Vision Library,是一個(gè)跨平臺(tái)的計(jì)算機(jī)視覺庫。OpenCV是由英特爾公司發(fā)起并參與開發(fā),以BSD許可證授權(quán)發(fā)行,可以在商業(yè)和研究領(lǐng)域中免費(fèi)使用。OpenCV可用于開發(fā)實(shí)時(shí)的圖像處理、計(jì)算機(jī)視覺以及模式識(shí)別程序。

在視覺處理中,opencv使用是基礎(chǔ)的部分,所以在板卡使用過程中,opecv使用是第一道關(guān)。接下來我給大家介紹一下,在jetson nano里面使用opencv的python版本和c++版本的過程,其中c++使用部分會(huì)分別給大家介紹cmake和makefile編譯兩種方法。

歡迎關(guān)注微信公眾號(hào):羽林君,或者添加作者個(gè)人微信:become_me

oepcv介紹:

OpenCV 的目標(biāo)是為計(jì)算機(jī)視覺需要解決的問題提供工具。在某些情況下,函數(shù)庫中的高級功能可以有效解決計(jì)算機(jī)視覺中的問題。即使遇到不能夠一次性解決的問題,函數(shù)庫中的基礎(chǔ)組件也具有足夠的完備性來增強(qiáng)解決方案的性能,以應(yīng)對任意的計(jì)算機(jī)視覺難題。

基本功能:

opencv的應(yīng)用領(lǐng)域非常廣泛,包括圖像拼接、圖像降噪、產(chǎn)品質(zhì)檢、人機(jī)交互人臉識(shí)別、動(dòng)作識(shí)別、動(dòng)作跟蹤、無人駕駛,此外,它還提供了機(jī)器學(xué)習(xí)模塊,你可以使用正態(tài)貝葉斯、K最近鄰、支持向量機(jī)、決策樹、隨機(jī)森林、人工神經(jīng)網(wǎng)絡(luò)等機(jī)器學(xué)習(xí)算法。

注:示例代碼參考了其他博主文章。

opencv-python使用:

opencv-python使用比較簡單,import導(dǎo)入cv2,這樣我們就可以使用opencv-python模塊的函數(shù)執(zhí)行我們需要的動(dòng)作了,下面介紹了一個(gè)比較簡單的圖像轉(zhuǎn)換的demo。

opencv-python安裝

pip3?install?opencv-python

示例代碼:

"""
彩圖轉(zhuǎn)灰度圖
"""

#import 導(dǎo)入模塊,每次使用模塊中的函數(shù)都要是定是哪個(gè)模塊。
#from…import *?導(dǎo)入模塊,每次使用模塊中的函數(shù),直接使用函數(shù)就可以了;注因?yàn)橐呀?jīng)知道該函數(shù)是那個(gè)模塊中的了
from?skimage.color?import?rgb2gray?#skimage圖形處理庫?color是顏色空間轉(zhuǎn)換子模塊?pip?install?scikit-image
import?numpy?as?np?
import?matplotlib.pyplot?as?plt??#matlab的python庫??pip?install?matplotlib
from?PIL?import?Image?#?Python?Imaging?Library?圖像處理庫?pip?install?pillow
import?cv2?

#圖像灰度化

#cv2的方式
img?=?cv2.imread("/home/lyn/Pictures/318c944a7daa47eaa37eaaf8354fe52f.jpeg")
h,w?=?img.shape[:2]?#獲取圖片的high和wide
img_gray=np.zeros([h,w],img.dtype)?#創(chuàng)建一張和當(dāng)前圖片大小一樣的單通道圖片
for?i?in?range(h):
????for?j?in?range(w):
????????m?=?img[i,j]
????????img_gray[i,j]?=int(m[0]*0.11+m[1]*0.59+m[2]*0.3)?#將BGR坐標(biāo)轉(zhuǎn)換為gray坐標(biāo)
print(img_gray)
print("image?show?grap:%s"%img_gray)
cv2.imshow("imageshow?gray",?img_gray)

#plt方式
plt.subplot(221)?#表示將整個(gè)圖像窗口分為2行2列,?當(dāng)前位置為1.
img?=?plt.imread("/home/lyn/Pictures/318c944a7daa47eaa37eaaf8354fe52f.jpeg")
plt.imshow(img)
print("----image?lenna?-----")
print(img)

#灰度化
img_gray?=?rgb2gray(img)
plt.subplot(222)
plt.imshow(img_gray,cmap="gray")
print("-----image?gray-------")
print(img_gray)

#二值化
img_binary?=?np.where(img_gray?>=?0.5,?1,?0)?
print("-----imge_binary------")
print(img_binary)
print(img_binary.shape)

#plt方式
plt.subplot(223)?
plt.imshow(img_binary,?cmap='gray')
plt.show()

opencv c++使用:

opencv-c++安裝一般系統(tǒng)使用opencv 需要我們自己去官網(wǎng):https://opencv.org,下載自己對應(yīng)的包,然后camke->make->make install ,直至把編譯好的opencv的文件安裝到指定目錄。

但是在Jetson Nano的鏡像包中,預(yù)裝了opencv4,版本的話是從4.1版本以后的。我使用命令查詢之后,我安裝的鏡像opencv版本是4.1.1

jetson@jetson-desktop:/usr/include/opencv4/opencv2$?opencv_version?
4.1.1

C++下開發(fā)Opencv需要進(jìn)行一些額外的配置,先看一下opencv的頭文件位置。

jetson中,opencv的頭文件在這個(gè)目錄 /usr/include/opencv4/,待會(huì)要把該目錄寫如編譯鏈接文件中去。

鏈接文件位置:ls libopencv*

具體路徑為 /usr/lib/aarch64-linux-gnu,待會(huì)也要把該目錄寫如編譯鏈接文件中去。

在c++開發(fā)中,我們一般會(huì)使用make工具或者cmake工具,幫助我們進(jìn)行打包編譯,這里我也給大家分享makefle和cmake兩種c++調(diào)用opencv的庫。

makefile

Makefile文件分享,注意這里 LIBS 鏈接的opencv鏈接的具體文件,需要一個(gè)一個(gè)寫進(jìn)去。這里我隨便寫了幾個(gè)常用的包,大家可以按照需求自行添加。

OBJS?=?*.o?
CFLAGS?=?-Wall?-g?-std=c++11
CC?=?gcc
CPP?=?g++
INCLUDES?+=-I??/usr/include/opencv4/?-I?/usr/local/include?#編譯頭文件目錄
LIBS?+=?-L/usr/lib/aarch64-linux-gnu?-lopencv_core?-lopencv_imgcodecs?-lopencv_imgproc?-lopencv_highgui?-lopencv_objdetect?#鏈接具體使用的庫

target:${OBJS}
#?g++??-o?target?boost_thread.o??-llua?-ldl?
?@echo?"--?start?"?${CC}?${CFLAGS}?${OBJS}??-o?$@??${INCLUDES}??${LIBS}
?$(CPP)?${CFLAGS}?${OBJS}??-o?$@??${INCLUDES}??${LIBS}

clean:
?-rm?-f?*.o?core?*.core?target

%.o:%.cpp?#將src目錄下所有的.cpp文件編譯成.o文件
?${CPP}?${CFLAGS}?${INCLUDES}?-c??$<

代碼show_img.cpp:

#include?<opencv2/opencv.hpp>
#include?<iostream>
using?namespace?std;
using?namespace?cv;

int?main(int?argc,char**?argv)
{
?std::cout<<"hello?opencv"<<std::endl;

?//灰度圖顯示
?Mat?src?=?imread("/home/jetson/lyn_work/c++/sp_noise.png",IMREAD_GRAYSCALE);//讀取進(jìn)來的數(shù)據(jù)以矩陣的形勢,第二個(gè)參數(shù)代表顯示一張灰度圖像。
?if?(src.empty())?
?{
??std::cout<<"could?not?load?image"<<endl;//如果圖片不存在?將無法讀取,打印到終端。
?}
?//超過屏幕的圖像無法顯示時(shí)候調(diào)用此函數(shù)。
?namedWindow("輸入窗口",?WINDOW_GUI_EXPANDED);//創(chuàng)建了一個(gè)新窗口,參數(shù)1表示名稱,第二個(gè)參數(shù)代表一個(gè)自由的比例
?imshow("輸入窗口",?src);//表示顯示在新創(chuàng)建的輸入窗口上,第一個(gè)參數(shù)表示窗口名稱,src表示數(shù)據(jù)對象Mat?
?waitKey(0);//執(zhí)行到這句,程序阻塞。參數(shù)表示延時(shí)時(shí)間。單位ms
?destroyAllWindows();//銷毀前面創(chuàng)建的顯示窗口
?return?0;
}

編譯并執(zhí)行:

make?

./target

在這里插入圖片描述

cmake

對應(yīng)CMakeLists.txt文件內(nèi)容:cmake編譯中,我們使用的鏈接對應(yīng)OpenCV動(dòng)態(tài)庫文件就不用像Makefile文件那樣要一個(gè)個(gè)添加了,cmake相當(dāng)與添加了所有的opencv鏈接文件,這個(gè)是很方便的。所以后面cmake的類子里面,我多寫了一個(gè)范例。

cmake_minimum_required(?VERSION?2.8?)

#?聲明一個(gè)?cmake?工程
project(opencv_learn)

#?設(shè)置編譯模式
#set(?CMAKE_BUILD_TYPE?"Debug"?)

#添加OPENCV庫
#指定OpenCV版本,代碼如下
#find_package(OpenCV?4.2?REQUIRED)
#如果不需要指定OpenCV版本,代碼如下
find_package(OpenCV?REQUIRED)

include_directories(
?./src/)


#添加OpenCV頭文件
include_directories(${OpenCV_INCLUDE_DIRS})

#顯示OpenCV_INCLUDE_DIRS的值
message(${OpenCV_INCLUDE_DIRS})

FILE(GLOB_RECURSE?TEST_SRC
?#src/*.cpp
?#src/*.c
?${CMAKE_SOURCE_DIR}/*.cpp
?${CMAKE_SOURCE_DIR}/*.cp
?)

#?添加一個(gè)可執(zhí)行程序
#?語法:add_executable(?程序名?源代碼文件?)
add_executable(target?show_img.cpp?${TEST_SRC})

#?將庫文件鏈接到可執(zhí)行程序上
target_link_libraries(target??${OpenCV_LIBS})

執(zhí)行cmake編譯:

mkdir?build
cmake??..
make

demo1 :使用了和make示例同樣的show_img.cpp代碼文件,內(nèi)容參考上面:

./target

demo2 :使用C++編程讀取CSI攝像頭,可以看到已經(jīng)可以正常的顯示視頻流圖像了,但是由于vnc連接的原因,顏色也有些失真.
CMakeLists.txt增加兩行:

add_executable(open_csi?open_csi.cpp?${TEST_SRC})

target_link_libraries(open_csi??${OpenCV_LIBS})

open_csi.cpp代碼文件如下:

#include?<iostream>
#include?<string>
#include?<opencv4/opencv2/opencv.hpp>
#include?<opencv4/opencv2/core.hpp>
#include?<opencv4/opencv2/highgui.hpp>
#include?<opencv4/opencv2/imgproc.hpp>
#include?<opencv4/opencv2/objdetect.hpp>
#include?<opencv4/opencv2/imgproc/types_c.h>
#include?<opencv4/opencv2/videoio.hpp>

using?namespace?std;
using?namespace?cv;

string?gstreamer_pipeline?(int?capture_width,?int?capture_height,?int?display_width,?int?display_height,?int?framerate,?int?flip_method)
{
????return?"nvarguscamerasrc?!?video/x-raw(memory:NVMM),?width=(int)"?+?to_string(capture_width)?+?",?height=(int)"?+
???????????to_string(capture_height)?+?",?format=(string)NV12,?framerate=(fraction)"?+?to_string(framerate)?+
???????????"/1?!?nvvidconv?flip-method="?+?to_string(flip_method)?+?"?!?video/x-raw,?width=(int)"?+?to_string(display_width)?+?",?height=(int)"?+
???????????to_string(display_height)?+?",?format=(string)BGRx?!?videoconvert?!?video/x-raw,?format=(string)BGR?!?appsink";
}

int?main(?int?argc,?char**?argv?)
{
????int?capture_width?=?1280?;
????int?capture_height?=?720?;
????int?display_width?=?1280?;
????int?display_height?=?720?;
????int?framerate?=?60?;
????int?flip_method?=?0?;

????//創(chuàng)建管道
????string?pipeline?=?gstreamer_pipeline(capture_width,
????capture_height,
????display_width,
????display_height,
????framerate,
????flip_method);
????std::cout?<<?"使用gstreamer管道:?nt"?<<?pipeline?<<?"n";

????//管道與視頻流綁定
????VideoCapture?cap(pipeline,?CAP_GSTREAMER);
????if(!cap.isOpened())
????{
????????std::cout<<"打開攝像頭失敗."<<std::endl;
????????return?(-1);
????}

????//創(chuàng)建顯示窗口
????namedWindow("CSI?Camera",?WINDOW_AUTOSIZE);
????Mat?img;

????//逐幀顯示
????while(true)
????{
????????if?(!cap.read(img))
????????{
????????????std::cout<<"捕獲失敗"<<std::endl;
????????????break;
????????}
????????int?new_width,new_height,width,height,channel;
????????????width=img.cols;
????????????height=img.rows;
????????????channel=img.channels();


????????//調(diào)整圖像大小
????????new_width=640;
????????if(width>800)
??????????{
?????????????new_height=int(new_width*1.0/width*height);
???????????}
?????????resize(img,?img,?cv::Size(new_width,?new_height));

????????imshow("CSI?Camera",img);

????????int?keycode?=?cv::waitKey(30)?&?0xff?;?//ESC鍵退出
????????????if?(keycode?==?27)?break?;
????}

????cap.release();
????destroyAllWindows()?;
}


顯示效果如截圖所示:

結(jié)語

這就是我對jetson nano使用opencv的基礎(chǔ)分享,后面我們就可以基于opencv做一些更有意思的項(xiàng)目了,比如人臉識(shí)別,物體識(shí)別,姿態(tài)識(shí)別等等。如果大家有更好的想法和需求,也歡迎大家加我好友交流分享哈。


作者:良知猶存,白天努力工作,晚上原創(chuàng)公號(hào)號(hào)主。公眾號(hào)內(nèi)容除了技術(shù)還有些人生感悟,一個(gè)認(rèn)真輸出內(nèi)容的職場老司機(jī),也是一個(gè)技術(shù)之外豐富生活的人,攝影、音樂 and 籃球。關(guān)注我,與我一起同行。

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

一個(gè)程序員,喜歡寫文章,還喜歡打籃球,也喜歡吉他鋼琴的駁雜之人。日常更新自己,分享包括但不限于C/C++、嵌入式、物聯(lián)網(wǎng)、Linux等編程學(xué)習(xí)筆記,同時(shí),公眾號(hào)內(nèi)包含大量的學(xué)習(xí)資源。歡迎關(guān)注,一同交流學(xué)習(xí),共同進(jìn)步!