java - 为什么 OpenCV-Java 无法连接到 mjpeg-stream(来自烧瓶)而 Python3/cv2 可以做到?
问题描述
Python/flask 服务器 (server.py) 充当 WebCam 代理。
- Python3+cv2(opencv4.1.1)使用cv2.VideoCapture()可以连接并显示流(client.py)。
- Java+OpenCV (1.8.0_192 / opencv-4.1.1_vc14_vc15) 似乎有连接问题 (client.java)。
注意:虽然 cv2.open(url) 只发送一个 GET 请求。使用 Java/OpenCV,服务器看到 2 个 GET 请求并且捕获保持关闭。
下面是源代码和命令行调用……在 Win7Pro 上运行。
有什么想法为什么它不能在 Java 中工作?
服务器.py
# Python 3.7.4 / cv2.__version__=4.1.1
# WebCam-Server providing MJPEG stream
# OK:Firefox_62.0.3 OK_SLOW:VLC_3.0.8 OK:Py3.7+cv2
# FAIL:Java+OpenCV_4.1.1
# python server.py
import cv2, time
from flask import Flask, Response, request
VIDEO_CAPTURE_ID=0
app=Flask(__name__)
def get_frames():
camera=cv2.VideoCapture(VIDEO_CAPTURE_ID, cv2.CAP_DSHOW)
while True:
val, img=camera.read()
if not val: continue
yield cv2.imencode('.jpg', img)[1].tobytes()
time.sleep(0.01)
def gen():
while True:
for frame in get_frames():
yield (b'--frame\r\n'
b'Content-Type:image/jpeg\r\n'
b'Content-Length: '+(b'%d' % len(frame))+b'\r\n'
b'\r\n'+frame+b'\r\n')
@app.route('/videofeed')
def f_videofeed():
print("@app.route('/videofeed') .....")
return Response(gen(), mimetype='multipart/x-mixed-replace;boundary=frame')
if __name__=='__main__':
app.run(host='localhost', threaded=True, debug=True) # default port 5000
客户端.py
# Python 3.7.4 / cv2.__version__=4.1.1
# Client ...
# python client.py
client.py
import cv2
fg=cv2.VideoCapture()
print(fg)
addr="http://localhost:5000/videofeed?cam.mjpg"
print(addr)
tst=fg.open(addr)
print(tst)
for ii in range(5):
val,frm=fg.read()
s1=frm.tostring()
print("%d : %r %r %r ... %r" % (ii, val, len(s1), s1[:6], s1[-6:]))
fg.release()
客户端.java
// Java 1.8.0_192 / opencv-4.1.1_vc14_vc15
// Client
// opencv-411.jar/opencv_java411.dll vom InstallDir nach "." kopiert
// javac -cp opencv-411.jar client.java && java.exe -cp .;opencv-411.jar client
import org.opencv.core.Core;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.Videoio;
public class client{
public static void main (String args[]) throws InterruptedException
{
Boolean tst=false;
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture fg=new VideoCapture(Videoio.CAP_FFMPEG);
System.out.println(fg);
String addr="http://localhost:5000/videofeed?cam.mjpg";
tst=fg.open(addr);
System.out.println(tst);
System.out.println(fg.getBackendName());
}
}
客户端控制台窗口
test_flask_opencv>
test_flask_opencv>javac -cp opencv-411.jar client.java && java.exe -cp .;opencv-411.jar client
org.opencv.videoio.VideoCapture@28d93b30
[ERROR:0] global C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\videoio\src\cap.cpp (116) cv::VideoCapture::open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.1.1) C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\videoio\src\cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): http://localhost:5000/videofeed?cam.mjpg in function 'c
v::icvExtractPattern'
false
Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.1.1) C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\videoio\src\cap.cpp:220: error: (-215:Assertion failed) api != 0 in function 'cv::VideoCap
ture::getBackendName'
]
at org.opencv.videoio.VideoCapture.getBackendName_0(Native Method)
at org.opencv.videoio.VideoCapture.getBackendName(VideoCapture.java:164)
at client.main(client.java:23)
test_flask_opencv>
test_flask_opencv>
test_flask_opencv>python client.py
<VideoCapture 0013DDC0>
http://localhost:5000/videofeed?cam.mjpg
True
FFMPEG
0 : True 921600 b'\x00\x00\x00\x00\x00\x00' ... b'\x00\x00\x00\x00\x00\x00'
1 : True 921600 b'\x9e\xa9\x8c\x9a\xa5\x88' ... b'`vok\x81z'
2 : True 921600 b'\xc3\xa3\x91\xc1\xa1\x8f' ... b'\x90\x80\x85\x8d}\x82'
3 : True 921600 b'\xb4\x9d\x8f\xb0\x99\x8b' ... b'\x9d\x90\x8c\x8f\x82~'
4 : True 921600 b'\xcd\x94\x86\xd2\x99\x8b' ... b'\xb8\x89\x85\xac}y'
test_flask_opencv>
服务器控制台窗口
test_flask_opencv>
test_flask_opencv>python server.py
* Serving Flask app "server" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 156-364-938
* Running on http://localhost:5000/ (Press CTRL+C to quit)
@app.route('/videofeed') .....
127.0.0.1 - - [10/Nov/2019 17:45:44] "GET /videofeed?cam.mjpg HTTP/1.1" 200 -
@app.route('/videofeed') .....
127.0.0.1 - - [10/Nov/2019 17:45:45] "GET /videofeed?cam.mjpg HTTP/1.1" 200 -
test_flask_opencv>
test_flask_opencv>
test_flask_opencv>
test_flask_opencv>python server.py
* Serving Flask app "server" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Restarting with stat
* Debugger is active!
* Debugger PIN: 156-364-938
* Running on http://localhost:5000/ (Press CTRL+C to quit)
@app.route('/videofeed') .....
127.0.0.1 - - [10/Nov/2019 17:46:17] "GET /videofeed?cam.mjpg HTTP/1.1" 200 -
解决方案
推荐阅读
- python - 在嵌套循环中使用枚举 [Python]
- python - django 管理静态文件通过`collectstatic`上传到s3,但在本地运行时不提供
- c++ - 无法通过 QUdpSocket 多播接收
- java - 如何运行 Cucumber 6 CLI
- qml - 如何使用 QML Repeater 作为页面指示器?
- serenity-platform - ImageUploadEditor : "上传的文件不是图片!"
- node.js - 在 react 和 node 中设置 socket io
- python - 为什么 Python exe 文件这么大?
- python - QTableWidget.itemAt() 的最后一行返回 None 而不是 QTableWidgetItem
- amazon-workspaces - 低带宽的 AWS Workspace