目錄
?
簡(jiǎn)介
Maven
軟件環(huán)境
JavaCV-Examples
OpenCV Cookbook Examples
概述
示例
OpenCV文檔
如何使用JavaCV示例
示例代碼的組織結(jié)構(gòu)
示例列表
Why Scala?
學(xué)習(xí)地址
圖像簡(jiǎn)單處理代碼示例
1.打開(kāi)保存一張圖
?2.畫(huà)直線
3.畫(huà)圓圈
4.畫(huà)折現(xiàn)
5.添加文字水印
6.裁剪并局部放大
7.人臉檢測(cè)
視頻簡(jiǎn)單處理代碼示例
1.打開(kāi)視頻文件
2.抓取視頻指定時(shí)間的幀保存為圖像
3.錄屏
4.給視頻添加水印
簡(jiǎn)介
JavaCV使用來(lái)自JavaCPP預(yù)設(shè)庫(kù)的包裝器,這些庫(kù)是計(jì)算機(jī)視覺(jué)領(lǐng)域的研究人員常用的庫(kù)(OpenCV, FFmpeg, libdc1394, FlyCapture, Spinnaker, OpenKinect, librealsense, CL PS3 Eye Driver, videoInput, ARToolKitPlus, flandmark, Leptonica和Tesseract),并提供實(shí)用程序類,使其功能更容易在Java平臺(tái)(包括Android)上使用。
JavaCV還具有硬件加速全屏圖像顯示(CanvasFrame和GLCanvasFrame),易于使用的方法在多核上并行執(zhí)行代碼(parallel),用戶友好的相機(jī)和投影儀的幾何和顏色校準(zhǔn)(GeometricCalibrator, ProCamGeometricCalibrator, ProCamColorCalibrator),特征點(diǎn)的檢測(cè)和匹配(ObjectFinder),一組實(shí)現(xiàn)投影儀-相機(jī)系統(tǒng)的直接圖像對(duì)齊的類(主要是GNImageAligner,projectvetransformer, projvecolortransformer, ProCamTransformer和ReflectanceInitializer),一個(gè)blob分析包(Blobs),以及JavaCV類中的其他功能。其中一些類也有OpenCL和OpenGL對(duì)應(yīng)的類,它們的名字以CL結(jié)尾或以GL開(kāi)頭,例如:JavaCVCL, GLCanvasFrame等。
要學(xué)習(xí)如何使用API,因?yàn)槟壳叭狈ξ臋n,請(qǐng)參考下面的示例用法部分以及示例程序,包括兩個(gè)Android (FacePreview.java和RecordActivity.java),也可以在samples目錄中找到。您還可以參考ProCamCalib和ProCamTracker的源代碼,以及從OpenCV2 Cookbook和相關(guān)wiki頁(yè)面移植的示例。
Maven
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.8</version>
</dependency>
軟件環(huán)境
要使用JavaCV,首先需要下載并安裝以下軟件:
Java SE 7或更新版本的實(shí)現(xiàn):
-
OpenJDK OpenJDK: Download and install or
-
Oracle JDK http://www.oracle.com/technetwork/java/javase/downloads/ or
-
IBM JDK http://www.ibm.com/developerworks/java/jdk/
此外,雖然并不總是必需的,JavaCV的一些功能也依賴于:
-
CL Eye Platform SDK (Windows only) CL - Downloads - Code Laboratories
CL Eye平臺(tái)SDK為開(kāi)發(fā)人員提供了對(duì)相機(jī)使用和操作的完全訪問(wèn)和控制。為了可移植性和易用性,所提供的api作為標(biāo)準(zhǔn)的基于C的函數(shù)公開(kāi),還包括作為基線測(cè)試框架的所有示例應(yīng)用程序的完整源代碼。
-
Android SDK API 21 or newer http://developer.android.com/sdk/
-
JOCL and JOGL from JogAmp JogAmp.org - Java graphics, audio, media and processing libraries exposing OpenGL, OpenCL, OpenAL and OpenMAX
JogAmp是用于3D圖形、多媒體和處理的高性能Java?庫(kù)的家。
JOGL, JOCL和JOAL提供跨平臺(tái)Java?語(yǔ)言綁定到OpenGL?,OpenCL?,OpenAL和OpenMAX api。
最后,請(qǐng)確保所有內(nèi)容具有相同的位,32位和64位模塊在任何情況下都不能混合。
JavaCV-Examples
這個(gè)項(xiàng)目包含使用JavaCV和其他javacpp-presets項(xiàng)目中的庫(kù)包裝器的示例。
-
OpenCV_Cookbook - Robert laganiere的書(shū)《OpenCV Computer Vision Application Programming Cookbook》中提供的示例的JavaCV版本。Cookbook中的原始示例是用c++編寫(xiě)的,這里它們被翻譯為使用JavaCV API。
-
使用flandmark庫(kù)的示例。
-
使用JVM包裝flr /Point Grey FlyCapture SDK的示例。
-
使用JVM包裝Flir/Point Grey Spinnaker SDK的示例
OpenCV Cookbook Examples
概述
OpenCV Cookbook示例說(shuō)明了OpenCV與JavaCV的使用。這些例子是從Robert laganie:1的書(shū)《OpenCV 2計(jì)算機(jī)視覺(jué)應(yīng)用程序編程指南》中移植的c++代碼開(kāi)始的。后來(lái)更新為第四版的書(shū)“OpenCV計(jì)算機(jī)視覺(jué)應(yīng)用程序編程 Cookbook第四版”。書(shū)中的示例使用OpenCV c++ API。在這里,它們被轉(zhuǎn)換為使用JavaCV和JavaCPP-Presets api。
OpenCV(開(kāi)源計(jì)算機(jī)視覺(jué))是一個(gè)包含數(shù)百種算法的庫(kù),用于計(jì)算機(jī)視覺(jué)和視頻分析。OpenCV可以通過(guò)兩種方式在JVM上運(yùn)行。首先是由OpenCV提供的Java包裝器。第二種是基于JavaCPP (JVM的c++包裝器引擎)的包裝器,稱為OpenCV JavaCPP預(yù)置。還有其他計(jì)算機(jī)視覺(jué)相關(guān)庫(kù)的JavaCPP預(yù)設(shè),如:FFmpeg, libdc1394, PGR FlyCapture, OpenKinect, videoInput, ARToolKitPlus, landmark等。JavaCV結(jié)合了JavaCPP預(yù)置中的庫(kù),并添加了一些額外的功能,使它們更容易在JVM上使用。
OpenCV Cookbook Examples項(xiàng)目演示了通過(guò)JavaCV和OpenCV JavaCPP預(yù)設(shè)使用OpenCV。當(dāng)前的版本更新是為了匹配Robert laganie:1的書(shū)“OpenCV計(jì)算機(jī)視覺(jué)應(yīng)用程序編程 Cookbook第二版”的第二版。它旨在與OpenCV .4一起使用(JavaCV 1節(jié))。
雖然示例中的代碼主要是用Scala編寫(xiě)的,Scala是領(lǐng)先的JVM語(yǔ)言之一。它可以很容易地轉(zhuǎn)換為Java和運(yùn)行在JVM上的其他語(yǔ)言,例如Groovy。在大多數(shù)JVM語(yǔ)言中,JavaCV API的使用非常相似。在Java版本中提供了一些示例。
示例
下面是一個(gè)快速預(yù)覽,將原始c++示例與使用JavaCV包裝器的Scala和Java代碼進(jìn)行比較。
下面是一個(gè)原始的c++示例,它打開(kāi)一個(gè)圖像(沒(méi)有錯(cuò)誤檢查),創(chuàng)建一個(gè)窗口,在窗口中顯示圖像,并等待5秒后退出。
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
int main() {
// Read an image
cv::Mat src = cv::imread("data/boldt.jpg");
display(src, "Input")
// Apply Laplacian filter
cv::Mat dest;
cv::Laplacian(src, dest, src.depth(), 1, 3, 0, BORDER_DEFAULT);
display(dest, "Laplacian");
// wait key for 5000 ms
cv::waitKey(5000);
return 1;
}
//---------------------------------------------------------------------------
void display(Mat image, char* caption) {
// Create image window named "My Image"
cv::namedWindow(caption);
// Show image on window
cv::imshow(caption, image);
}
上面的c++示例使用JavaCV包裝器轉(zhuǎn)換為Scala:
import javax.swing._
import org.bytedeco.javacv._
import org.bytedeco.opencv.global.opencv_core._
import org.bytedeco.opencv.global.opencv_imgcodecs._
import org.bytedeco.opencv.global.opencv_imgproc._
import org.bytedeco.opencv.opencv_core._
object MyFirstOpenCVApp extends App {
// Read an image.
val src = imread("data/boldt.jpg")
display(src, "Input")
// Apply Laplacian filter
val dest = new Mat()
Laplacian(src, dest, src.depth(), 1, 3, 0, BORDER_DEFAULT)
display(dest, "Laplacian")
//---------------------------------------------------------------------------
/** Display `image` with given `caption`. */
def display(image: Mat, caption: String): Unit = {
// Create image window named "My Image."
val canvas = new CanvasFrame(caption, 1)
// Request closing of the application when the image window is closed.
canvas.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
// Convert from OpenCV Mat to Java Buffered image for display
val converter = new OpenCVFrameConverter.ToMat()
// Show image on window
canvas.showImage(converter.convert(image))
}
}
現(xiàn)在用Java表達(dá)相同的例子。請(qǐng)注意,JavaCV API的使用與Scala和Java代碼中的完全相同。唯一的實(shí)際區(qū)別是,在Java代碼中更冗長(zhǎng),您必須顯式地為每個(gè)變量提供類型,而在Scala中這是可選的。
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.opencv.opencv_core.Mat;
import javax.swing.*;
import java.awt.image.BufferedImage;
import static opencv_cookbook.OpenCVUtilsJava.toBufferedImage;
import static org.bytedeco.opencv.global.opencv_core.BORDER_DEFAULT;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgproc.Laplacian;
public class MyFirstOpenCVAppInJava {
public static void main(String[] args) {
// Read an image.
final Mat src = imread("data/boldt.jpg");
display(src, "Input");
// Apply Laplacian filter
final Mat dest = new Mat();
Laplacian(src, dest, src.depth(), 1, 3, 0, BORDER_DEFAULT);
display(dest, "Laplacian");
}
//---------------------------------------------------------------------------
static void display(Mat image, String caption) {
// Create image window named "My Image".
final CanvasFrame canvas = new CanvasFrame(caption, 1.0);
// Request closing of the application when the image window is closed.
canvas.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// Convert from OpenCV Mat to Java Buffered image for display
final BufferedImage bi = toBufferedImage(image);
// Show image on window.
canvas.showImage(bi);
}
}
OpenCV文檔
如果您正在尋找一個(gè)特定的OpenCV操作,請(qǐng)使用OpenCV文檔(OpenCV documentation index)??焖偎阉骺蛱貏e有用。該文檔包含了C/ c++ OpenCV API可選使用方式的描述。
如何使用JavaCV示例
OpenCV Cookbook示例項(xiàng)目是作為Robert laganie:1的書(shū)“OpenCV計(jì)算機(jī)視覺(jué)應(yīng)用程序編程Cookbook第二版”的伙伴。推薦的方法是在對(duì)如何將Cookbook的c++代碼轉(zhuǎn)換為JavaCV有疑問(wèn)時(shí)閱讀Cookbook并參考JavaCV示例。這本書(shū)解釋了算法是如何工作的。JavaCV示例只提供了與JavaCV API細(xì)節(jié)相關(guān)的非常簡(jiǎn)短的注釋。
使用JavaCV示例的最簡(jiǎn)單方法是在線瀏覽位于[src/main]中的代碼。您也可以使用Git或ZIP文件將其下載到計(jì)算機(jī)上。
通過(guò)最小的設(shè)置,您可以輕松地在自己的計(jì)算機(jī)上執(zhí)行示例。這是JavaCV的好處之一——它提供了在各種平臺(tái)上運(yùn)行OpenCV所需的所有二進(jìn)制文件。在第1章的README中解釋了這個(gè)設(shè)置。
示例代碼的組織結(jié)構(gòu)
代碼被組織成與Cookbook第1版中的章節(jié)相對(duì)應(yīng)的包,例如opencv_cookbook.chapter8。它與第二版非常相似。個(gè)別的例子大致對(duì)應(yīng)于書(shū)中每一章的章節(jié)。
第1章描述了運(yùn)行這些示例的IDE設(shè)置,給出了一個(gè)加載和顯示圖像的基本示例,以及一個(gè)執(zhí)行基本圖像處理的基本GUI示例。
示例列表
第一章:使用圖像
-
Ex1MyFirstOpenCVApp -加載圖像并在窗口中顯示它(CanvasFrame)
-
Ex2MyFirstGUIFXApp -使用ScalaFX (JavaFX包裝器)構(gòu)建的簡(jiǎn)單GUI應(yīng)用程序。該應(yīng)用程序在左側(cè)有兩個(gè)按鈕“打開(kāi)圖像”和“處理”。打開(kāi)的圖像顯示在中間。當(dāng)按下“處理”按鈕時(shí),圖像被翻轉(zhuǎn)過(guò)來(lái),其紅色和藍(lán)色通道被交換。有關(guān)Swing版本,請(qǐng)參閱Ex2MyFirstGUIApp。
-
Ex2MyFirstGUIApp -使用Scala Swing構(gòu)建的簡(jiǎn)單GUI應(yīng)用程序。該應(yīng)用程序在左側(cè)有兩個(gè)按鈕“打開(kāi)圖像”和“處理”。打開(kāi)的圖像顯示在中間。當(dāng)按下“處理”按鈕時(shí),圖像被翻轉(zhuǎn)過(guò)來(lái),其紅色和藍(lán)色通道被交換。有關(guān)JavaFX版本,請(qǐng)參閱Ex2MyFirstGUIFXApp。
-
Ex3LoadAndSave -讀取,保存,顯示和繪制圖像。
第二章:操縱像素
-
Ex1Salt -設(shè)置個(gè)人,隨機(jī)選擇,像素到一個(gè)固定的值。使用ImageJ的ImageProcessor來(lái)訪問(wèn)像素。
-
Ex2ColorReduce -通過(guò)相同的方式修改所有波段的顏色值來(lái)減少圖像中的顏色。
-
ex3銳化-使用內(nèi)核卷積銳化圖像:filter2D()。
-
Ex4BlendImages -混合兩個(gè)圖像使用加權(quán)加法:cvAddWeighted()。
-
ex5roillogo -使用感興趣的區(qū)域?qū)⑿D像粘貼到較大的圖像中:IplROI和cvCopy()。
第三章:用類處理圖像
-
Ex1ColorDetector -將RGB顏色與目標(biāo)顏色進(jìn)行比較,與目標(biāo)顏色相似的顏色在輸出圖像中被分配為白色,其他像素被設(shè)置為黑色。
-
Ex2ColorDetectorSimpleApplication—第一個(gè)示例的處理過(guò)程相同,但演示了一個(gè)簡(jiǎn)單的UI。
-
ex3colordetectormvapplication—相同的處理是第一個(gè)示例,但演示了一個(gè)更詳細(xì)的UI。
-
Ex4ConvertingColorSpaces -類似于第一個(gè)例子,但是顏色距離是在Lab*顏色空間中計(jì)算的。說(shuō)明cvtColor函數(shù)的使用。
第四章:用直方圖計(jì)算像素
-
Ex1ComputeHistogram -使用實(shí)用程序類Histogram1D計(jì)算直方圖,并將值打印到屏幕上。
-
Ex2ComputeHistogramGraph -顯示使用實(shí)用程序類Histogram1D創(chuàng)建的直方圖的圖形。
-
Ex3Threshold -使用OpenCV threshold()方法將圖像中的像素分離為前景和背景。
-
Ex4InvertLut—通過(guò)反轉(zhuǎn)其查找表來(lái)創(chuàng)建倒立的圖像。
-
Ex5EqualizeHistogram -使用直方圖均衡化增強(qiáng)圖像。
-
Ex6ContentDetectionGrayscale -使用灰度圖像中區(qū)域的直方圖來(lái)創(chuàng)建“模板”,通過(guò)整個(gè)圖像來(lái)檢測(cè)與該模板相似的像素。舉例說(shuō)明cvCalcBackProject()方法的使用。
-
Ex7ContentDetectionColor -使用區(qū)域直方圖在彩色圖像中創(chuàng)建“模板”,通過(guò)整個(gè)圖像來(lái)檢測(cè)與該模板相似的像素。依賴于工具類ColorHistogram和ContentFinder。
-
Ex8MeanShiftDetector -使用彩色圖像中的區(qū)域直方圖來(lái)創(chuàng)建“模板”,使用mean shift算法在另一張圖像中找到“模板”的最佳匹配位置。舉例說(shuō)明cvMeanShift()方法的用法。
-
使用輔助類ImageComparator計(jì)算圖像相似度度量。
-
執(zhí)行直方圖和查找表操作的Helper類,對(duì)應(yīng)于OpenCV Cookbook中部分c++類Histogram1D的樣例代碼。舉例說(shuō)明OpenCV方法的使用:cvLUT(), cvEqualizeHist(), cvCreateHist(), cvCalcHist(), cvQueryHistValue_1D(), cvReleaseHist()。
-
ColorHistogram -幫助類簡(jiǎn)化了彩色圖像cvCalcHist()方法的使用。
-
使用cvCalcBackProject()方法進(jìn)行模板匹配的輔助類。
-
ImageComparator -使用cvCompareHist()計(jì)算圖像相似度的輔助類。
第五章:用形態(tài)學(xué)操作變換圖像
-
侵蝕和擴(kuò)張-形態(tài)侵蝕和擴(kuò)張:cvErode()和cvDilate()。
-
Ex2OpeningAndClosing -形態(tài)學(xué)打開(kāi)和關(guān)閉:cvMorphologyEx()。
-
Ex3EdgesAndCorners -使用形態(tài)學(xué)過(guò)濾器檢測(cè)邊緣和角落。
-
Ex4WatershedSegmentation -圖像分割使用分水嶺算法。
-
Ex5GrabCut -使用grabCut()從背景中分離對(duì)象。
-
MorphoFeatures -等價(jià)于同名的c++類,包含形態(tài)學(xué)角檢測(cè)的方法。
-
WatershedSegmenter -“使用分水嶺分割圖像”一節(jié)的輔助類。
第六章:過(guò)濾圖像
-
Ex1LowPassFilter -模糊與高斯濾波器。
-
Ex2MedianFilter -用中值濾波器去除噪聲。
-
Ex3DirectionalFilters -使用Sobel邊緣檢測(cè)濾波器。
-
使用拉普拉斯濾波器的邊緣檢測(cè)。
-
LaplacianZC -計(jì)算Laplacian和過(guò)零,用于Ex4Laplacian。
第七章:提取線條、輪廓和組件
-
Ex1CannyOperator -檢測(cè)輪廓與Canny算子。
-
Ex2HoughLines -使用標(biāo)準(zhǔn)Hough變換方法檢測(cè)線條。
-
Ex3HoughLineSegments -使用概率霍夫變換方法檢測(cè)線段。
-
Ex4HoughCircles -使用霍夫變換方法檢測(cè)圓。
-
Ex5ExtractContours -使用連接的組件從二值圖像中提取輪廓。
-
Ex6ShapeDescriptors -計(jì)算各種形狀描述符:邊界框,封閉圓,近似多邊形,凸殼,質(zhì)心。
-
LineFinder -使用概率霍夫變換方法檢測(cè)線段的輔助類,用于Ex3HoughLineSegments。
第八章:發(fā)現(xiàn)興趣點(diǎn)
-
Ex1HarrisCornerMap -計(jì)算哈里斯角強(qiáng)度圖像。
-
Ex2HarrisCornerDetector -使用Harris角強(qiáng)度圖像來(lái)檢測(cè)定位良好的角,用一個(gè)角取代幾個(gè)位置較近的檢測(cè)(模糊)。使用HarrisDetector輔助類。
-
Ex3GoodFeaturesToTrack -使用GoodFeatures跟蹤檢測(cè)器的例子。
-
Ex4FAST -使用FAST檢測(cè)器的示例。
-
Ex5SURF -使用SURF檢測(cè)器的示例。
-
Ex6SIFT -使用SIFT檢測(cè)器的示例。
-
幫助類,用于哈里斯角強(qiáng)度圖像的檢測(cè)和定位。距離較近的探測(cè)(模糊)被單個(gè)探測(cè)取代。
第九章:發(fā)現(xiàn)興趣點(diǎn)
-
Ex2TemplateMatching -從第一個(gè)圖像(模板)和第二個(gè)圖像中找到一個(gè)小補(bǔ)丁之間的最佳匹配。
-
ex7descripbingsurf -計(jì)算SURF特征,提取它們的描述符,并在同一物體的兩幅圖像之間找到最佳匹配的描述符。
第十章:估計(jì)圖像中的投影關(guān)系
-
Ex1FindChessboardCorners -演示了相機(jī)校準(zhǔn)步驟之一,在校準(zhǔn)板中檢測(cè)棋盤(pán)模式。
-
Ex2CalibrateCamera -相機(jī)校準(zhǔn)示例,展示了如何校正光學(xué)器件可能引入的幾何變形。使用CameraCalibrator助手類。
-
Ex3ComputeFundamentalMatrix -使用兩幅圖像之間檢測(cè)和匹配的特征,計(jì)算描述兩幅圖像之間投影關(guān)系的基本矩陣。
-
Ex4MatchingUsingSampleConsensus -說(shuō)明RANSAC(隨機(jī)抽樣共識(shí))策略的使用。大多數(shù)計(jì)算是由RobustMatcher helper類完成的。
-
Ex5Homography -描述兩個(gè)圖像中點(diǎn)之間關(guān)系的另一種方法,使用homography。展示了如何將一個(gè)對(duì)象的部分視圖的兩個(gè)圖像拼接在一起的示例。大多數(shù)計(jì)算是由RobustMatcher helper類完成的。
-
實(shí)現(xiàn)攝像機(jī)校準(zhǔn)算法的助手類。
-
RobustMatcher -實(shí)現(xiàn)基于RANSAC的算法,例如Ex4MatchingUsingSampleConsensus和Ex5Homography。
第十一章:處理視頻序列
-
Ex1ReadVideoSequence -讀取并顯示視頻。
-
Ex2ProcessVideoFrames -使用Canny邊緣檢測(cè)器處理視頻文件中的幀;在屏幕上顯示輸出視頻。使用輔助類VideoProcessor。
-
Ex3WriteVideoSequence -使用Canny邊緣檢測(cè)器處理視頻文件中的幀;將輸出寫(xiě)入視頻文件。使用輔助類VideoProcessor。
-
Ex4TrackingFeatures -跟蹤視頻中的移動(dòng)對(duì)象,標(biāo)記屏幕上顯示的視頻中的跟蹤點(diǎn)。大部分的實(shí)現(xiàn)是在FeatureTracker helper類中完成的。
-
Ex5ForegroundSegmenter -通過(guò)背景估計(jì)檢測(cè)視頻中的移動(dòng)對(duì)象。背景使用“簡(jiǎn)單”移動(dòng)平均方法建模,實(shí)現(xiàn)在助手類“BGFBSegmenter”中。
-
Ex6MOGMotionDetector -一個(gè)更復(fù)雜的運(yùn)動(dòng)檢測(cè)器,使用混合高斯方法建模背景。
-
BGFBSEgmenter -通過(guò)使用移動(dòng)平均線對(duì)背景建模,將“靜態(tài)”背景與“移動(dòng)”前景分開(kāi)。使用的例子'Ex5ForegroundSegmenter'。
-
FeatureTracker -使用光流算法跟蹤移動(dòng)特征,例如Ex4TrackingFeatures。
-
VideoProcessor -處理視頻文件的輔助類,加載和應(yīng)用處理到單獨(dú)的幀,例如:Ex2ProcessVideoFrames, Ex3WriteVideoSequence, Ex4TrackingFeatures和Ex5ForegroundSegmenter。
第十五章:OpenCV高級(jí)特性
-
Ex1FaceDetection -使用預(yù)訓(xùn)練的深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)模型檢測(cè)圖像中的人臉。
其他通用技術(shù)
-
OpenCVUtils -讀取和寫(xiě)入圖像文件,顯示圖像,繪制圖像的特征,OpenCV圖像和數(shù)據(jù)表示之間的轉(zhuǎn)換。
Why Scala?
之所以選擇Scala,是因?yàn)樗菾ava更具表現(xiàn)力。您可以用更少的代碼獲得相同的結(jié)果。更小的樣板代碼使示例更容易閱讀和理解。編譯后的Scala代碼速度很快,類似于Java和c++。
與Java或c++不同,Scala支持編寫(xiě)腳本——無(wú)需顯式編譯即可執(zhí)行的代碼。Scala也有一個(gè)控制臺(tái),稱為REPL,可以在其中輸入單行代碼并當(dāng)場(chǎng)執(zhí)行。這兩個(gè)特性使得在Scala中構(gòu)建基于opencv的程序比在Java中更容易。最后但并非最不重要的一點(diǎn)是,IDE對(duì)Scala的支持達(dá)到了成熟的程度,允許輕松地創(chuàng)建、修改和執(zhí)行Scala代碼。特別是,用于JetBrains IDEA的Scala插件工作得非常好。還有對(duì)Eclipse和NetBeans的Scala支持。
學(xué)習(xí)地址
https://github.com/bytedeco/javacv
Welcome to OpenCV Java Tutorials documentation! — OpenCV Java Tutorials 1.0 documentation
GitHub - bytedeco/javacv-examples: Examples of using JavaCV / OpenCV library on Java Virtual Machine
關(guān)于類、API等如果有疑問(wèn)可以看考o(jì)penCV、FFmpeg的方法介紹,javaCV只不過(guò)是對(duì)它們的封裝,或者直接問(wèn)ChatGPT吧,簡(jiǎn)單高效!
圖像簡(jiǎn)單處理代碼示例
圖像處理的API主要集中在opencv-4.6.0-1.5.8.jar包下,該包有兩個(gè)目錄“bytedeco.opencv”與“opencv”,兩個(gè)package下有許多同名的類與靜態(tài)方法,請(qǐng)盡量采用“bytedeco.opencv”package下的類與方法。
1.打開(kāi)保存一張圖
// 打開(kāi)一張圖
Mat image = imread("D:\\2projects_database\\javacvdemo\\src\\main\\java\\com\\example\\img\\future_city.jpg");
// 保存圖像 imwrite("D:\\2projects_database\\javacvdemo\\src\\main\\java\\com\\example\\img\\future_city_add_text.jpg", image);
?2.畫(huà)直線
/**
* 畫(huà)直線
* @param image 圖片
* @param x1 起點(diǎn)橫坐標(biāo)
* @param y1 起點(diǎn)縱坐標(biāo)
* @param x2 終點(diǎn)橫坐標(biāo)
* @param y2 終點(diǎn)縱坐標(biāo)
* @param color 線條顏色
*/
public static void drawLine(Mat image, int x1, int y1, int x2, int y2, Scalar color) {
Point pt1 = new Point(x1, y1);
Point pt2 = new Point(x2, y2);
line(image, pt1, pt2, color);
}
3.畫(huà)圓圈
/**
* 畫(huà)圓圈
* @param image 圖像
* @param x 圓心橫坐標(biāo)
* @param y 圓心縱坐標(biāo)
* @param radius 半徑
* @param color 線條顏色
* @param thickness 線條厚度
* @param lineType 線條類型
* @param shift 坐標(biāo)值的小數(shù)位數(shù)
*/
public static void drawCircle(Mat image, int x, int y, int radius, Scalar color, int thickness, int lineType, int shift) {
Point center = new Point(x, y);
circle(image, center, radius, color, thickness, lineType, shift);
}
4.畫(huà)折現(xiàn)
/**
* 畫(huà)折現(xiàn)
* @param image 圖像
* @param points 端點(diǎn)數(shù)組
* @param color 線條顏色
*/
public static void drawCurve(Mat image, Point[] points, Scalar color) {
for (int i = 0; i < points.length - 1; i++) {
line(image, points[i], points[i+1], color);
}
}
5.添加文字水印
/**
* 添加文字水印
* @param image 圖像
* @param text 文字內(nèi)容
* @param position 文字位置
* @param fontFace 字體類型
* @param fontScale 字體大小
* @param color 字體顏色
*/
public static void addTextWatermark(Mat image, String text, Point position, int fontFace, double fontScale, Scalar color) {
putText(image, text, position, fontFace, fontScale, color);
}
6.裁剪并局部放大
/**
* 裁剪圖像并局部放大
* @param image 圖像
* @param x 起始位置橫坐標(biāo)
* @param y 起始位置縱坐標(biāo)
* @param width 裁剪寬度
* @param height 裁剪高度
* @param zoomFactor 放大倍數(shù)
*/
public static void cropAndZoomImage(Mat image, int x, int y, int width, int height, int zoomFactor) {
Rect roi = new Rect(x, y, width, height);
Mat croppedImage = new Mat(image, roi);
resize(croppedImage, croppedImage, new Size(width*zoomFactor, height*zoomFactor));
// 保存圖像
imwrite("D:\\2projects_database\\javacvdemo\\src\\main\\java\\com\\example\\img\\cropAndZoomImage.png", croppedImage);
System.out.println("resize rows:" + croppedImage.rows());
System.out.println("resize cols:" + croppedImage.cols());
}
7.人臉檢測(cè)
package com.example.img.code;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
import static org.bytedeco.opencv.global.opencv_imgproc.LINE_8;
import static org.bytedeco.opencv.global.opencv_imgproc.rectangle;
/**
* @Author yrz
* @create 2023/5/12 11:22
* @Description TODO
*/
public class FaceDetector {
public static void main(String[] args) {
// Load the image
Mat image = imread("D:/2projects_database/javacvdemo/src/main/java/com/example/img/face.jpg");
// Load the face cascade classifier
CascadeClassifier faceCascade = new CascadeClassifier("D:/2projects_database/javacvdemo/src/main/java/com/example/img/haarcascade_frontalface_alt.xml");
// Detect faces in the image
RectVector faceDetections = new RectVector();
faceCascade.detectMultiScale(image, faceDetections);
// Draw a rectangle around each detected face
for (Rect rect : faceDetections.get()) {
rectangle(image, new Point(rect.x(), rect.y()), new Point(rect.x() + rect.width(), rect.y() + rect.height()),
new Scalar(0, 255, 0, 0), 2, LINE_8, 0);
}
// Save the image with the detected faces
imwrite("D:/2projects_database/javacvdemo/src/main/java/com/example/img/face_output.jpg", image);
}
}
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-772498.html
視頻簡(jiǎn)單處理代碼示例
視頻處理的API主要集中在javacv-1.5.8.jar包下。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-772498.html
1.打開(kāi)視頻文件
/**
* 打開(kāi)視頻文件
* @param filename
*/
public static void readDisplayVideo(String filename){
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(filename);
// Open video video file
try {
grabber.start();
} catch (FFmpegFrameGrabber.Exception e) {
e.printStackTrace();
}
// Prepare window to display frames
CanvasFrame canvasFrame = new CanvasFrame("Extracted Frame", 1);
canvasFrame.setCanvasSize(grabber.getImageWidth(), grabber.getImageHeight());
// Exit the example when the canvas frame is closed
canvasFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
long delay = Math.round(1000d / grabber.getFrameRate());
// Read frame by frame, stop early if the display window is closed
Frame frame;
try {
while ((frame = grabber.grab()) != null && canvasFrame.isVisible()) {
// Capture and show the frame
canvasFrame.showImage(frame);
// Delay
Thread.sleep(delay);
}
// Close the video file
grabber.release();
} catch (FFmpegFrameGrabber.Exception e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2.抓取視頻指定時(shí)間的幀保存為圖像
/**
* 抓取視頻指定時(shí)間的幀保存為圖像
* @param videoPath
* @param imagePath
* @param timeInSeconds
*/
public static void grabFrameAtTime(String videoPath, String imagePath, long timeInSeconds) {
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoPath);
Java2DFrameConverter converter = new Java2DFrameConverter();
try {
grabber.start();
grabber.setTimestamp(timeInSeconds);
Frame grab = grabber.grabImage();
BufferedImage bufferedImage = converter.getBufferedImage(grab, converter.getBufferedImageType(grab) ==
BufferedImage.TYPE_CUSTOM ? 1.0 : 1.0, false, null);
saveImage(bufferedImage, imagePath);
grabber.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void saveImage(BufferedImage image, String imagePath) {
try {
ImageIO.write(image, "jpg", new File(imagePath));
} catch (IOException e) {
e.printStackTrace();
}
}
3.錄屏
/**
* 錄屏
* @param filename 文件名稱
* @param seconds 時(shí)長(zhǎng)
*/
public static void recordScreen(String filename, int seconds) {
final int FRAME_RATE = 30;
final Dimension SCREEN_SIZE = Toolkit.getDefaultToolkit().getScreenSize();
// 創(chuàng)建錄屏對(duì)象,并設(shè)置相關(guān)屬性
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(filename, SCREEN_SIZE.width, SCREEN_SIZE.height);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setFormat("mp4");
recorder.setFrameRate(FRAME_RATE);
Java2DFrameConverter converter = new Java2DFrameConverter();
try {
// 初始化錄屏對(duì)象
recorder.start();
Robot robot = new Robot();
BufferedImage screenShot;
// 系統(tǒng)當(dāng)前時(shí)間
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
// 30秒后
LocalDateTime plus = now.plus(seconds, ChronoUnit.SECONDS);
System.out.println(plus);
// 開(kāi)始錄制
while (true) {
// 獲取屏幕截圖并寫(xiě)入文件
screenShot = robot.createScreenCapture(new Rectangle(SCREEN_SIZE));
recorder.record(converter.getFrame(screenShot));
// 停止時(shí)間
LocalDateTime time = LocalDateTime.now();
if(plus.isBefore(time)){
System.out.println(time);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 關(guān)閉錄制器
try {
recorder.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.給視頻添加水印
/**
* 給視頻添加水印
* @param filename
* @param outname
* @param picName
* @throws Exception
*/
public static void addWatermark (String filename, String outname, String picName) throws Exception {
// Load the video
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(filename);
grabber.start();
// Create a new video recorder
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outname, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setFormat("mp4");
recorder.setFrameRate(grabber.getFrameRate());
// 開(kāi)啟錄制
recorder.start();
// Create a new Java2DFrameConverter
Java2DFrameConverter converter = new Java2DFrameConverter();
// Create a new BufferedImage to hold the watermark image
// 圖片水印
BufferedImage watermarkImage = ImageIO.read(new File(picName));
// 自定義文字水印
// BufferedImage watermarkImage = createWatermarkImage("Hello, world!", new Font("Arial", Font.BOLD, 50),
// Color.WHITE, new Color(0, 0, 0, 0));
// Loop through each frame in the video
Frame frame;
while ((frame = grabber.grabFrame()) != null) {
// Convert the frame to a BufferedImage
BufferedImage image = converter.getBufferedImage(frame);
if(image == null){
continue;
}
// Create a new Graphics2D object to draw the watermark
Graphics2D g2d = image.createGraphics();
// Draw the watermark on the image
g2d.drawImage(watermarkImage, 0, 0, null);
// Dispose of the Graphics2D object
g2d.dispose();
// Convert the BufferedImage back to a Frame and write it to the output video
recorder.record(converter.convert(image));
}
// Stop the grabber and recorder
grabber.stop();
grabber.release();
recorder.stop();
recorder.release();
}
private static BufferedImage createWatermarkImage(String text, Font font, Color foreground, Color background) {
FontRenderContext frc = new FontRenderContext(null, true, true);
TextLayout layout = new TextLayout(text, font, frc);
Rectangle2D bounds = layout.getBounds();
BufferedImage image = new BufferedImage(
(int) bounds.getWidth(), (int) bounds.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
if (background != null) {
g2d.setBackground(background);
g2d.clearRect(0, 0, image.getWidth(), image.getHeight());
}
g2d.setFont(font);
g2d.setColor(foreground);
layout.draw(g2d, 0, -(float) bounds.getY());
if (background != null) {
ColorConvertOp colorConvert = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB),
null);
colorConvert.filter(image, image);
}
g2d.dispose();
return image;
}
到了這里,關(guān)于Java音視頻處理——JavaCV的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!