{"id":6642,"date":"2025-09-29T12:28:14","date_gmt":"2025-09-29T04:28:14","guid":{"rendered":"https:\/\/xinchewhd.com.cn\/?p=6642"},"modified":"2025-09-29T12:28:22","modified_gmt":"2025-09-29T04:28:22","slug":"%e3%80%90opencv-c-%e5%ae%9e%e6%88%98%e3%80%91rtsp-%e6%b5%81%e5%a4%84%e7%90%86%ef%bc%9a%e5%ae%9e%e6%97%b6%e6%92%ad%e6%94%be%e4%b8%8e%e9%80%90%e5%b8%a7%e4%bf%9d%e5%ad%98%e7%bb%88%e6%9e%81%e6%8c%87","status":"publish","type":"post","link":"https:\/\/xinchewhd.com.cn\/index.php\/opencv\/%e3%80%90opencv-c-%e5%ae%9e%e6%88%98%e3%80%91rtsp-%e6%b5%81%e5%a4%84%e7%90%86%ef%bc%9a%e5%ae%9e%e6%97%b6%e6%92%ad%e6%94%be%e4%b8%8e%e9%80%90%e5%b8%a7%e4%bf%9d%e5%ad%98%e7%bb%88%e6%9e%81%e6%8c%87\/","title":{"rendered":"\u3010OpenCV C++ \u5b9e\u6218\u3011RTSP \u6d41\u5904\u7406\uff1a\u5b9e\u65f6\u64ad\u653e\u4e0e\u9010\u5e27\u4fdd\u5b58\u7ec8\u6781\u6307\u5357"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><strong>\u6548\u679c<\/strong><strong><\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"422\" data-src=\"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-1024x422.png\" src=\"https:\/\/s.nmxc.ltd\/sakurairo_vision\/@2.6\/load_svg\/inload.svg\" onerror=\"imgError(this)\" alt=\"\" class=\"wp-image-6643 lazyload\" srcset=\"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-1024x422.png 1024w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-300x124.png 300w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-768x316.png 768w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-1536x633.png 1536w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png 1661w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><noscript><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"422\" src=\"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-1024x422.png\" alt=\"\" class=\"wp-image-6643\" srcset=\"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-1024x422.png 1024w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-300x124.png 300w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-768x316.png 768w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-1536x633.png 1536w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png 1661w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u9879\u76ee<\/strong><strong><\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"560\" data-src=\"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-1024x560.png\" src=\"https:\/\/s.nmxc.ltd\/sakurairo_vision\/@2.6\/load_svg\/inload.svg\" onerror=\"imgError(this)\" alt=\"\" class=\"wp-image-6644 lazyload\" srcset=\"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-1024x560.png 1024w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-300x164.png 300w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-768x420.png 768w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648.png 1534w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><noscript><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"560\" src=\"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-1024x560.png\" alt=\"\" class=\"wp-image-6644\" srcset=\"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-1024x560.png 1024w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-300x164.png 300w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-768x420.png 768w, https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648.png 1534w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>\u4ee3\u7801<\/strong><strong><\/strong><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;opencv2\/opencv.hpp&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;iostream&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;chrono&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;iomanip&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;sstream&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;fstream&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;string&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;thread&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;atomic&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;queue&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;mutex&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;condition_variable&gt;<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;sys\/stat.h&gt; \/\/ \u7528\u4e8e\u6587\u4ef6\u5939\u64cd\u4f5c (C++14\u517c\u5bb9)<\/em><br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#include<\/a>&nbsp;&lt;direct.h&gt; &nbsp; \/\/ Windows\u4e0b\u7684mkdir<\/em><br><br>\/\/ \u7ebf\u7a0b\u5b89\u5168\u7684\u5e27\u961f\u5217<br>class FrameQueue {<br>private:<br>&nbsp;std::queue&lt;std::pair&lt;cv::Mat, std::string&gt;&gt; queue;<br>&nbsp;std::mutex mtx;<br>&nbsp;std::condition_variable cond;<br>&nbsp;bool stop_flag =&nbsp;false;<br><br>public:<br><br>&nbsp;void push(const cv::Mat&amp; frame, const std::string&amp; filename) {<br>&nbsp; std::unique_lock&lt;std::mutex&gt; lock(mtx);<br>&nbsp; \/\/ \u6df1\u62f7\u8d1d\u5e27\uff0c\u56e0\u4e3a\u539f\u5e27\u53ef\u80fd\u4f1a\u88ab\u4fee\u6539\u6216\u91ca\u653e<br>&nbsp; queue.push(std::make_pair(frame.clone(), filename));<br>&nbsp; cond.notify_one();<br>&nbsp;}<br><br>&nbsp;bool pop(std::pair&lt;cv::Mat, std::string&gt;&amp; item) {<br>&nbsp; std::unique_lock&lt;std::mutex&gt; lock(mtx);<br>&nbsp; cond.wait(lock, &#91;this]() {&nbsp;return&nbsp;!queue.empty() || stop_flag; });<br><br>if&nbsp;(stop_flag &amp;&amp; queue.empty()) {<br>&nbsp; &nbsp;returnfalse;<br>&nbsp; }<br><br>&nbsp; item = queue.front();<br>&nbsp; queue.pop();<br>returntrue;<br>&nbsp;}<br><br>&nbsp;void&nbsp;stop() {<br>&nbsp; std::unique_lock&lt;std::mutex&gt; lock(mtx);<br>&nbsp; stop_flag =&nbsp;true;<br>&nbsp; cond.notify_all();<br>&nbsp;}<br><br>&nbsp;bool&nbsp;empty() {<br>&nbsp; std::unique_lock&lt;std::mutex&gt; lock(mtx);<br>return&nbsp;queue.empty();<br>&nbsp;}<br>};<br><br>\/\/ \u5168\u5c40\u53d8\u91cf<br>FrameQueue frameQueue;<br>std::atomic&lt;long long&gt; total_save_time{ 0 };<br>std::atomic&lt;int&gt; saved_frames_count{ 0 };<br>std::string imgFolder =&nbsp;\"img\"; \/\/ \u56fe\u7247\u4fdd\u5b58\u6587\u4ef6\u5939<br><br>\/\/ \u68c0\u67e5\u6587\u4ef6\u5939\u662f\u5426\u5b58\u5728 (C++14\u517c\u5bb9\u65b9\u6cd5)<br>bool folderExists(const std::string&amp; folderPath) {<br>&nbsp;struct&nbsp;stat&nbsp;info;<br>returnstat(folderPath.c_str(), &amp;info) == 0 &amp;&amp; (info.st_mode &amp; S_IFDIR);<br>}<br><br>\/\/ \u521b\u5efa\u6587\u4ef6\u5939 (C++14\u517c\u5bb9\u65b9\u6cd5)<br>bool createFolder(const std::string&amp; folderPath) {<br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#ifdef<\/a>&nbsp;_WIN32<\/em><br>return&nbsp;_mkdir(folderPath.c_str()) == 0;<br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#else<\/a><\/em><br>return&nbsp;mkdir(folderPath.c_str(), 0733) == 0;<br><em><a href=\"javascript:;\" target=\"_blank\"  rel=\"nofollow\" >#endif<\/a><\/em><br>}<br><br>\/\/ \u68c0\u67e5\u5e76\u521b\u5efa\u56fe\u7247\u4fdd\u5b58\u6587\u4ef6\u5939<br>bool&nbsp;ensureImageFolderExists() {<br>&nbsp;\/\/ \u68c0\u67e5\u6587\u4ef6\u5939\u662f\u5426\u5b58\u5728<br>if&nbsp;(folderExists(imgFolder)) {<br>&nbsp; std::cout &lt;&lt;&nbsp;\"\u4f7f\u7528\u56fe\u7247\u4fdd\u5b58\u6587\u4ef6\u5939: \"&nbsp;&lt;&lt; imgFolder &lt;&lt; std::endl;<br>returntrue;<br>&nbsp;}<br><br>&nbsp;\/\/ \u5982\u679c\u4e0d\u5b58\u5728\uff0c\u5c1d\u8bd5\u521b\u5efa\u6587\u4ef6\u5939<br>if&nbsp;(createFolder(imgFolder)) {<br>&nbsp; std::cout &lt;&lt;&nbsp;\"\u521b\u5efa\u56fe\u7247\u4fdd\u5b58\u6587\u4ef6\u5939: \"&nbsp;&lt;&lt; imgFolder &lt;&lt; std::endl;<br>returntrue;<br>&nbsp;}<br><br>&nbsp;std::cerr &lt;&lt;&nbsp;\"\u9519\u8bef: \u65e0\u6cd5\u521b\u5efa\u56fe\u7247\u4fdd\u5b58\u6587\u4ef6\u5939\"&nbsp;&lt;&lt; std::endl;<br>returnfalse;<br>}<br><br>\/\/ \u4fdd\u5b58\u56fe\u50cf\u7684\u7ebf\u7a0b\u51fd\u6570<br>void&nbsp;saveFrameThread() {<br>&nbsp;std::vector&lt;int&gt; compression_params;<br>&nbsp;compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);<br>&nbsp;compression_params.push_back(100);<br><br>while&nbsp;(true) {<br>&nbsp; std::pair&lt;cv::Mat, std::string&gt; item;<br>if&nbsp;(!frameQueue.pop(item)) {<br>&nbsp; &nbsp;break;<br>&nbsp; }<br><br>&nbsp; auto start_time = std::chrono::high_resolution_clock::now();<br><br>&nbsp; bool saveResult = cv::imwrite(item.second, item.first);<br>&nbsp; \/\/bool saveResult = cv::imwrite(item.second, item.first, compression_params);<br><br>&nbsp; auto end_time = std::chrono::high_resolution_clock::now();<br>&nbsp; auto duration = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(end_time - start_time);<br><br>if&nbsp;(!saveResult) {<br>&nbsp; &nbsp;std::cerr &lt;&lt;&nbsp;\"\u9519\u8bef: \u65e0\u6cd5\u4fdd\u5b58\u5e27: \"&nbsp;&lt;&lt; item.second &lt;&lt; std::endl;<br>&nbsp; }<br>else&nbsp;{<br>&nbsp; &nbsp;long long save_time = duration.count();<br>&nbsp; &nbsp;total_save_time += save_time;<br>&nbsp; &nbsp;saved_frames_count++;<br><br>&nbsp; &nbsp;std::cout &lt;&lt;&nbsp;\"\u5e27\u5df2\u4fdd\u5b58: \"&nbsp;&lt;&lt; item.second&lt;&lt;&nbsp;\" (\u4fdd\u5b58\u65f6\u95f4: \"&nbsp;&lt;&lt; save_time &lt;&lt;&nbsp;\"ms)\"&nbsp;&lt;&lt; std::endl;<br>&nbsp; }<br>&nbsp;}<br>}<br><br>\/\/ \u4fdd\u5b58\u56fe\u50cf\u7684\u7ebf\u7a0b\u51fd\u6570<br>void&nbsp;saveFrameThread2() {<br>&nbsp;std::vector&lt;int&gt; compression_params;<br>&nbsp;compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);<br>&nbsp;compression_params.push_back(100); &nbsp;\/\/ \u8d28\u91cf<br><br>while&nbsp;(true) {<br>&nbsp; std::pair&lt;cv::Mat, std::string&gt; item;<br>if&nbsp;(!frameQueue.pop(item)) {<br>&nbsp; &nbsp;break;<br>&nbsp; }<br><br>&nbsp; auto start_time = std::chrono::high_resolution_clock::now();<br><br>&nbsp; \/\/ \u7f16\u7801\u56fe\u50cf<br>&nbsp; std::vector&lt;uchar&gt; buffer;<br>&nbsp; auto encode_start = std::chrono::high_resolution_clock::now();<br>&nbsp; cv::imencode(\".jpg\", item.first, buffer, compression_params);<br>&nbsp; auto encode_end = std::chrono::high_resolution_clock::now();<br><br>&nbsp; \/\/ \u5199\u5165\u6587\u4ef6<br>&nbsp; auto write_start = std::chrono::high_resolution_clock::now();<br>&nbsp; std::ofstream ofs(item.second, std::ios::binary);<br>&nbsp; ofs.write(reinterpret_cast&lt;char*&gt;(buffer.data()), buffer.size());<br>&nbsp; ofs.close();<br>&nbsp; auto write_end = std::chrono::high_resolution_clock::now();<br><br>&nbsp; auto end_time = std::chrono::high_resolution_clock::now();<br>&nbsp; auto total_duration = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(end_time - start_time);<br>&nbsp; auto encode_duration = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(encode_end - encode_start);<br>&nbsp; auto write_duration = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(write_end - write_start);<br><br>if&nbsp;(!ofs) {<br>&nbsp; &nbsp;std::cerr &lt;&lt;&nbsp;\"\u9519\u8bef: \u65e0\u6cd5\u4fdd\u5b58\u5e27: \"&nbsp;&lt;&lt; item.second &lt;&lt; std::endl;<br>&nbsp; }<br>else&nbsp;{<br>&nbsp; &nbsp;long long total_time = total_duration.count();<br>&nbsp; &nbsp;long long encode_time = encode_duration.count();<br>&nbsp; &nbsp;long long write_time = write_duration.count();<br>&nbsp; &nbsp;total_save_time += total_time;<br>&nbsp; &nbsp;saved_frames_count++;<br><br>&nbsp; &nbsp;std::cout &lt;&lt;&nbsp;\"\u5e27\u5df2\u4fdd\u5b58: \"&nbsp;&lt;&lt; item.second<br>&nbsp; &nbsp; &lt;&lt;&nbsp;\" (\u603b\u65f6\u95f4: \"&nbsp;&lt;&lt; total_time &lt;&lt;&nbsp;\"ms, \u7f16\u7801: \"&nbsp;&lt;&lt; encode_time &lt;&lt;&nbsp;\"ms, \u5199\u5165: \"&nbsp;&lt;&lt; write_time &lt;&lt;&nbsp;\"ms)\"&nbsp;&lt;&lt; std::endl;<br>&nbsp; }<br>&nbsp;}<br>}<br><br>\/\/ \u663e\u793a\u4f7f\u7528\u8bf4\u660e<br>void printUsage(const std::string&amp; programName) {<br>&nbsp;std::cout &lt;&lt;&nbsp;\"\u4f7f\u7528\u65b9\u6cd5: \"&nbsp;&lt;&lt; programName &lt;&lt;&nbsp;\" &lt;RTSP_URL&gt;\"&nbsp;&lt;&lt; std::endl;<br>&nbsp;std::cout &lt;&lt;&nbsp;\"\u793a\u4f8b: \"&nbsp;&lt;&lt; programName &lt;&lt;&nbsp;\" rtsp:\/\/username:password@192.168.1.100:554\/stream\"&nbsp;&lt;&lt; std::endl;<br>&nbsp;std::cout &lt;&lt;&nbsp;\"\u6ce8\u610f: \u5982\u679cURL\u4e2d\u5305\u542b\u7279\u6b8a\u5b57\u7b26(\u5982&amp;)\uff0c\u8bf7\u5c06\u6574\u4e2aURL\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\"&nbsp;&lt;&lt; std::endl;<br>&nbsp;std::cout &lt;&lt; std::endl;<br>&nbsp;std::cout &lt;&lt;&nbsp;\"\u63a7\u5236\u547d\u4ee4:\"&nbsp;&lt;&lt; std::endl;<br>&nbsp;std::cout &lt;&lt;&nbsp;\" &nbsp;q\/Q &nbsp; &nbsp; &nbsp;- \u9000\u51fa\u7a0b\u5e8f\"&nbsp;&lt;&lt; std::endl;<br>&nbsp;std::cout &lt;&lt;&nbsp;\" &nbsp;\u7a7a\u683c\u952e &nbsp; - \u6682\u505c\/\u7ee7\u7eed\u64ad\u653e\"&nbsp;&lt;&lt; std::endl;<br>&nbsp;std::cout &lt;&lt;&nbsp;\" &nbsp;s\/S &nbsp; &nbsp; &nbsp;- \u663e\u793a\u4fdd\u5b58\u7edf\u8ba1\u4fe1\u606f\"&nbsp;&lt;&lt; std::endl;<br>&nbsp;std::cout &lt;&lt;&nbsp;\" &nbsp;c\/C &nbsp; &nbsp; &nbsp;- \u6e05\u96f6\u7edf\u8ba1\u4fe1\u606f\"&nbsp;&lt;&lt; std::endl;<br>}<br><br>int main(int argc, char* argv&#91;]) {<br><br>&nbsp;\/\/ \u68c0\u67e5\u547d\u4ee4\u884c\u53c2\u6570<br>if&nbsp;(argc != 2) {<br>&nbsp; std::cerr &lt;&lt;&nbsp;\"\u9519\u8bef: \u9700\u8981\u63d0\u4f9bRTSP URL\u4f5c\u4e3a\u53c2\u6570\"&nbsp;&lt;&lt; std::endl;<br>&nbsp; printUsage(argv&#91;0]);<br>return&nbsp;-1;<br>&nbsp;}<br><br>&nbsp;\/\/ \u4ece\u547d\u4ee4\u884c\u53c2\u6570\u83b7\u53d6RTSP URL<br>&nbsp;std::string rtspUrl = argv&#91;1];<br>&nbsp;std::cout &lt;&lt;&nbsp;\"\u4f7f\u7528RTSP URL: \"&nbsp;&lt;&lt; rtspUrl &lt;&lt; std::endl;<br><br><br>&nbsp;\/\/ \u68c0\u67e5\u5e76\u521b\u5efa\u56fe\u7247\u4fdd\u5b58\u6587\u4ef6\u5939<br>if&nbsp;(!ensureImageFolderExists()) {<br>&nbsp; std::cerr &lt;&lt;&nbsp;\"\u9519\u8bef: \u65e0\u6cd5\u521b\u5efa\u6216\u8bbf\u95ee\u56fe\u7247\u4fdd\u5b58\u6587\u4ef6\u5939\uff0c\u7a0b\u5e8f\u5c06\u9000\u51fa\"&nbsp;&lt;&lt; std::endl;<br>return&nbsp;-1;<br>&nbsp;}<br><br>&nbsp;\/\/ \u6253\u5f00\u89c6\u9891\u6d41<br>&nbsp;cv::VideoCapture&nbsp;cap(rtspUrl, cv::CAP_FFMPEG);<br><br>if&nbsp;(!cap.isOpened()) {<br>&nbsp; std::cerr &lt;&lt;&nbsp;\"\u9519\u8bef: \u65e0\u6cd5\u6253\u5f00RTSP\u6d41\"&nbsp;&lt;&lt; std::endl;<br>return&nbsp;-1;<br>&nbsp;}<br><br>&nbsp;\/\/ \u83b7\u53d6\u89c6\u9891\u6d41\u7684\u57fa\u672c\u4fe1\u606f<br>&nbsp;double fps = cap.get(cv::CAP_PROP_FPS);<br>&nbsp;int frameWidth = static_cast&lt;int&gt;(cap.get(cv::CAP_PROP_FRAME_WIDTH));<br>&nbsp;int frameHeight = static_cast&lt;int&gt;(cap.get(cv::CAP_PROP_FRAME_HEIGHT));<br>&nbsp;std::cout &lt;&lt;&nbsp;\"RTSP\u6d41\u4fe1\u606f: \"&nbsp;&lt;&lt; frameWidth &lt;&lt;&nbsp;\"x\"&nbsp;&lt;&lt; frameHeight &lt;&lt;&nbsp;\" at \"&nbsp;&lt;&lt; fps &lt;&lt;&nbsp;\" FPS\"&nbsp;&lt;&lt; std::endl;<br><br>&nbsp;\/\/ \u521b\u5efa\u4fdd\u5b58\u7ebf\u7a0b<br>&nbsp;std::thread saveThread(saveFrameThread);<br><br>&nbsp;\/\/ \u521b\u5efa\u7a97\u53e3<br>&nbsp;cv::namedWindow(\"RTSP Stream\", cv::WINDOW_NORMAL);<br>&nbsp;cv::resizeWindow(\"RTSP Stream\", frameWidth \/ 4, frameHeight \/ 4);<br><br>&nbsp;\/\/ \u4e3b\u5faa\u73af<br>&nbsp;cv::Mat frame;<br>while&nbsp;(true) {<br>&nbsp; \/\/ \u8bfb\u53d6\u4e00\u5e27<br>if&nbsp;(!cap.read(frame)) {<br>&nbsp; &nbsp;std::cerr &lt;&lt;&nbsp;\"\u9519\u8bef: \u8bfb\u53d6\u5e27\u5931\u8d25\"&nbsp;&lt;&lt; std::endl;<br>&nbsp; &nbsp;break;<br>&nbsp; }<br><br>&nbsp; \/\/ \u663e\u793a\u5e27<br>&nbsp; cv::imshow(\"RTSP Stream\", frame);<br><br>&nbsp; \/\/ \u83b7\u53d6\u5f53\u524d\u65f6\u95f4\uff08\u7cbe\u786e\u5230\u6beb\u79d2\uff09<br>&nbsp; auto now = std::chrono::system_clock::now();<br>&nbsp; auto now_ms = std::chrono::time_point_cast&lt;std::chrono::milliseconds&gt;(now);<br>&nbsp; auto epoch = now_ms.time_since_epoch();<br>&nbsp; auto value = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(epoch);<br>&nbsp; long long milliseconds = value.count();<br><br>&nbsp; \/\/ \u5c06\u6beb\u79d2\u65f6\u95f4\u6233\u8f6c\u6362\u4e3a\u53ef\u8bfb\u683c\u5f0f<br>&nbsp; std::time_t time_t_now = std::chrono::system_clock::to_time_t(now);<br>&nbsp; std::tm tm_struct;<br>&nbsp; localtime_s(&amp;tm_struct, &amp;time_t_now);<br>&nbsp; std::ostringstream oss;<br>&nbsp; oss &lt;&lt; std::put_time(&amp;tm_struct,&nbsp;\"%Y%m%d_%H%M%S_\") &lt;&lt; std::setfill('0') &lt;&lt; std::setw(3) &lt;&lt; (milliseconds % 1000);<br>&nbsp; std::string timestampStr = oss.str();<br><br>&nbsp; \/\/ \u6784\u5efa\u4fdd\u5b58\u56fe\u50cf\u7684\u6587\u4ef6\u540d\uff08\u5305\u542bimg\u6587\u4ef6\u5939\u8def\u5f84\uff09<br>&nbsp; std::string filename = imgFolder +&nbsp;\"\/frame_\"&nbsp;+ timestampStr +&nbsp;\".bmp\";<br><br>&nbsp; \/\/ \u5c06\u5e27\u548c\u6587\u4ef6\u540d\u6dfb\u52a0\u5230\u961f\u5217\uff08\u7531\u4fdd\u5b58\u7ebf\u7a0b\u5904\u7406\uff09<br>&nbsp; frameQueue.push(frame, filename);<br><br>&nbsp; \/\/ \u5904\u7406\u952e\u76d8\u8f93\u5165<br>&nbsp; int key = cv::waitKey(1) &amp; 0xFF;<br>if&nbsp;(key ==&nbsp;'q'&nbsp;|| key ==&nbsp;'Q') {<br>&nbsp; &nbsp;break;<br>&nbsp; }<br>elseif&nbsp;(key ==&nbsp;' ') {<br>&nbsp; &nbsp;while&nbsp;(true) {<br>&nbsp; &nbsp; int innerKey = cv::waitKey(0) &amp; 0xFF;<br>&nbsp; &nbsp;&nbsp;if&nbsp;(innerKey ==&nbsp;' ') {<br>&nbsp; &nbsp; &nbsp;break;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp;&nbsp;elseif&nbsp;(innerKey ==&nbsp;'q'&nbsp;|| innerKey ==&nbsp;'Q') {<br>&nbsp; &nbsp; &nbsp;cv::destroyAllWindows();<br>&nbsp; &nbsp; &nbsp;cap.release();<br>&nbsp; &nbsp; &nbsp;frameQueue.stop();<br>&nbsp; &nbsp; &nbsp;saveThread.join();<br>&nbsp; &nbsp; &nbsp;return&nbsp;0;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp;}<br>&nbsp; }<br>elseif&nbsp;(key ==&nbsp;'s'&nbsp;|| key ==&nbsp;'S') {<br>&nbsp; &nbsp;\/\/ \u663e\u793a\u7edf\u8ba1\u4fe1\u606f<br>&nbsp; &nbsp;if&nbsp;(saved_frames_count &gt; 0) {<br>&nbsp; &nbsp; double avg_save_time = static_cast&lt;double&gt;(total_save_time) \/ saved_frames_count;<br>&nbsp; &nbsp; std::cout &lt;&lt;&nbsp;\"\u4fdd\u5b58\u7edf\u8ba1: \"&nbsp;&lt;&lt; saved_frames_count &lt;&lt;&nbsp;\" \u5e27, \u5e73\u5747\u4fdd\u5b58\u65f6\u95f4: \"&lt;&lt; avg_save_time &lt;&lt;&nbsp;\"ms\"&nbsp;&lt;&lt; std::endl;<br>&nbsp; &nbsp;}<br>&nbsp; }<br>elseif&nbsp;(key ==&nbsp;'c'&nbsp;|| key ==&nbsp;'C') {<br>&nbsp; &nbsp;\/\/ \u6e05\u7a7a\u7edf\u8ba1\u4fe1\u606f<br>&nbsp; &nbsp;total_save_time = 0;<br>&nbsp; &nbsp;saved_frames_count = 0;<br>&nbsp; &nbsp;std::cout &lt;&lt;&nbsp;\"\u7edf\u8ba1\u4fe1\u606f\u5df2\u6e05\u96f6\"&nbsp;&lt;&lt; std::endl;<br>&nbsp; }<br>&nbsp;}<br><br>&nbsp;\/\/ \u91ca\u653e\u8d44\u6e90<br>&nbsp;cap.release();<br>&nbsp;cv::destroyAllWindows();<br><br>&nbsp;\/\/ \u505c\u6b62\u4fdd\u5b58\u7ebf\u7a0b\u5e76\u7b49\u5f85\u7ed3\u675f<br>&nbsp;frameQueue.stop();<br>&nbsp;saveThread.join();<br><br>&nbsp;\/\/ \u663e\u793a\u6700\u7ec8\u7edf\u8ba1\u4fe1\u606f<br>if&nbsp;(saved_frames_count &gt; 0) {<br>&nbsp; double avg_save_time = static_cast&lt;double&gt;(total_save_time) \/ saved_frames_count;<br>&nbsp; std::cout &lt;&lt;&nbsp;\"\u6700\u7ec8\u7edf\u8ba1: \"&nbsp;&lt;&lt; saved_frames_count &lt;&lt;&nbsp;\" \u5e27\u5df2\u4fdd\u5b58, \u5e73\u5747\u4fdd\u5b58\u65f6\u95f4: \"&lt;&lt; avg_save_time &lt;&lt;&nbsp;\"ms\"&nbsp;&lt;&lt; std::endl;<br>&nbsp;}<br><br>return&nbsp;0;<br>}<\/code><\/pre>\n","raw":"","protected":false},"excerpt":{"rendered":"<p>\u6548\u679c \u9879\u76ee \u4ee3\u7801<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"emotion":"","emotion_color":"","title_style":"","license":"","footnotes":""},"categories":[50,49],"tags":[],"class_list":["post-6642","post","type-post","status-publish","format-standard","hentry","category-c","category-opencv"],"post_thumbnail_image":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png","content_first_image":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png","post_medium_image_300":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png","post_thumbnail_image_624":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png","post_frist_image":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png","post_medium_image":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png","post_large_image":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png","post_full_image":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436.png","post_all_images":[{"imagesurl":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-1024x422.png","id":"image0"},{"imagesurl":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042800436-1024x422.png","id":"image1"},{"imagesurl":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-1024x560.png","id":"image2"},{"imagesurl":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2025\/09\/20250929042808648-1024x560.png","id":"image3"}],"videoAdId":"","listAd":"0","listAdId":"","listAdEvery":6,"total_comments":0,"category_name":"C++","post_date":"2025-09-29","like_count":"0","praiseWord":"\u9f13\u52b1","copyright_state":"","excitationAd":"0","rewardedVideoAdId":"","detailAdId":"","detailAd":"0","enterpriseMinapp":"0","audios":[],"postImageUrl":"https:\/\/wp-moto-1258805347.cos.ap-shanghai.myqcloud.com\/2023\/05\/20230519082947553.jpg","avatarurls":[],"related_posts":null,"pageviews":171,"next_post_id":6680,"next_post_title":"\u4e8e\u6d77\u5eb7SDK\u7684C++\u5b9e\u65f6\u89c6\u9891\u6d41\u9010\u5e27\u6293\u53d6\u5b58\u56fe\u5c0f\u5de5\u5177","previous_post_id":null,"previous_post_title":null,"_links":{"self":[{"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/posts\/6642","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/comments?post=6642"}],"version-history":[{"count":1,"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/posts\/6642\/revisions"}],"predecessor-version":[{"id":6645,"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/posts\/6642\/revisions\/6645"}],"wp:attachment":[{"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/media?parent=6642"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/categories?post=6642"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/xinchewhd.com.cn\/index.php\/wp-json\/wp\/v2\/tags?post=6642"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}