How to view TV Tuner component input with OpenCV? - opencv

I'm trying to use my tvtuner instead of a webcam with opencv.
The problem is that by default cvCaptureFromCAM(0) gives me the tv channel of the tv tuner, but what I actually want the input from my the RCA input of the tv tuner.
I have tried usingcvCaptureFromCAM(-1) to check if there are additional camera devices found within the tvtuner, but it only gives me the general tvtuner as an option.
Is there a way to change the channel of the input?

Probably not.
In Linux (and Windows is similar), the OpenCV cvCaptureFromCAM() only recognizes one input for each tuner/framegrabber/webcam. If your device shows up as multiple logical devices, then you can use the parameter of cvCaptureFromCAM() to select which logical device to use.
For example: if you have:
/dev/video
/dev/video0 <-- tv tuner, tuner input
/dev/video1 <-- tv tuner, rca input
cvCaptureFromCAM(0) will use /dev/video0 and
cvCaptureFromCAM(1) will use /dev/video1.
What might work is if you use some other program such as mythtv or tvtime (or something else on windows) to change the input for your tuner to your RCA input and then try running opencv again.

Related

OpenCV can't grab-retrieve on Windows 11

I have been using the "grab and retrieve" flow with OpenCV's VideoCapture on linux for a long time. Now migrating the code to Windows 11, it seems with the same USB Webcams that using retrieve is not working:
import sys
import cv2
camera_number = 2
print(f"video output encoding backends available to OpenCV: "
f"{[cv2.videoio_registry.getBackendName(backend) for backend in cv2.videoio_registry.getWriterBackends()]}")
print(f"camera video acquisition backends available to OpenCV: "
f"{[cv2.videoio_registry.getBackendName(backend) for backend in cv2.videoio_registry.getStreamBackends()]}")
video_stream = cv2.VideoCapture(camera_number, cv2.CAP_DSHOW)
if video_stream.isOpened():
print(f"successfully opened camera number {camera_number}")
else:
print(f"\nfailed to open camera number {camera_number}")
sys.exit(1)
print(f"OpenCV is using the following backend library for camera video acquisition: {video_stream.getBackendName()}")
success, image = video_stream.read()
if success:
print('read image succeeded')
else:
print('read image failed')
while video_stream.isOpened():
grabbed = video_stream.grab()
if grabbed:
print('image grab succeeded')
else:
print('image grab failed')
success, image = video_stream.retrieve()
if not success:
raise ValueError(f'image retrieve failed')
This code succeeds up until the retrieve().
Here's the full output:
video output encoding backends available to OpenCV: ['FFMPEG', 'GSTREAMER', 'INTEL_MFX', 'MSMF', 'CV_IMAGES', 'CV_MJPEG']
camera video acquisition backends available to OpenCV: ['FFMPEG', 'GSTREAMER', 'INTEL_MFX', 'MSMF', 'CV_IMAGES', 'CV_MJPEG']
successfully opened camera number 2
OpenCV is using the following backend library for camera video acquisition: DSHOW
read image succeeded
image grab succeeded
Traceback (most recent call last):
line 49, in <module>
raise ValueError(f'image retrieve failed')
ValueError: image retrieve failed
Process finished with exit code 1
As seen above, this is using DSHOW. Notably, none of the backends other than DSHOW seemed to manage to open the Webcam cameras, although the OpenCV API states them as supported.
Enabling the env variable OPENCV_VIDEOIO_DEBUG=1 does not reveal any warnings or errors.
The problem regards USB cameras but not the laptop's in-built camera: switching to camera number 0, the laptop's built-in camera, the same above code seamlessly works and manages to loop on grab and retrieve, but not with any of two Logitech Webcams (Logitech Brio and Logitech C390e) on this Windows 11 laptop.
Version info
opencv-python: 4.5.5.62
opencv-contrib-python: 4.5.5.62
winrt: 1.0.21033.1
python: 3.9.10
How would you approach this?
Ok, seems that (not much unlike on Linux) each webcam exposes more than one camera number through the OS, and by choosing one and not the other camera number, give or take a Windows Update bringing in some Logitech software update, it works.
Although both camera numbers manage opening the camera, only one of them enables the full flow. Enumerating the properties of each camera number through code is rough but through trial and error over just two of them camera numbers, it works.

Scan video for text string?

My goal is to find the title screen from a movie trailer. I need a service where I can search a video for a string, then return the frame with that string. Pretty obscure, does anything like this exist?
e.g. for this movie, I'd scan for "Sausage Party" and retrieve this frame:
Edit: I found the cloudsight api which would actually work except cost is prohibitive # $.04 per call assuming I need to split the video into 1s intervals and scan every image (at least 60 calls per video).
No exact service that I can find, but you could attempt to do this yourself...
ffmpeg -i sausage_party.mp4 -r 1 %04d.png
/usr/local/bin/parallel --no-notice -j 8 \
/usr/local/bin/tesseract -psm 6 -l eng {} {.} \
::: *.png
This extracts one frame a second from the video file, and then uses tesseract to extract the text via OCR into files of the same name as the image frame (eg. 0135.txt. However your results are going to vary massively depending on the font used and the quality of the video file.
You'd probably find it cheaper/easier to use something like Amazon Mechanical Turk , especially since the OCR is going to have a hard time doing this automatically.
Another option could be implementing this service by yourself using the Scene Text Detection and Recognition module in OpenCV (docs.opencv.org/3.0-beta/modules/text/doc/text.html). You can take a look at this video to get an idea of how such a system would operate. As pointed out above the accuracy would depend on the font used in the movie titles, the quality of the video files, and the OCR.
OpenCV relies on Tesseract as the underlying OCR but, alternatively, you could use the text detection and localization functions (docs.opencv.org/3.0-beta/modules/text/doc/erfilter.html) in OpenCV to find text areas in the image and then employ a different OCR to perform the recognition. The text detection and localization stage can be done very quickly thus achieving real time performance would be mostly a matter of picking a fast OCR.

Sobel edge detection filter not correct output: can it be because of some parameters

I am using http://shakithweblog.blogspot.kr/2012/12/getting-sobel-filter-application.html for zynq processor.
I am using his filter design in the PL part and running the hdmi test.
I am inputting this file
and my filtered output is coming like this:
I am trying to display 1920 * 1080 pixels.
Now lets assume its difficult for you see exactly my design/ or download the design and check it or even you are not familiar with the zynq board and all but is it possible to make some guess that why the filter output could be like this? and what can I try to make it correct. I need some suggestions.

Why is DirectShow dragging in unnecessary intermediate filters when making multiple input connections to my DirectShow Transform filter?

I have a DirectShow Transform filter written in Delphi 6 using the DSPACK component library. It is a simple audio mixer that creates a new input pin whenever a new connection is attempted. I say simple because once its media format is set, all connections to the its input pins or singular output pin are forced to conform to that media format. I build the filter chain manually, making all pin connections explicitly myself. I do not use any of the "intelligent rendering" calls, unless there is some way to trigger that unwanted behavior (in my case) accidentally.
NOTE: The Capture Filter is a standard DirectShow filter external to my application. My push source audio filter and simple audio mixer filters are being used as private, unregistered filters and are internal to my application.
I am having a weird problem that only occurs when I try to make multiple input connections to my mixer, which does indeed accept them. Currently, I am attempting to connect both a Capture Filter and my custom Push Source audio filter to my mixer filter. Whenever I try to do that the second upstream filter connection fails. Regardless of whether I connect the Capture Filter first or Push Source audio filter first, the second upstream filter connection always fails.
The first test I ran was to try connecting just the Capture Filter to the mixer. That worked fine.
The second test I ran was to try connecting just the Push Source audio filter to the mixer. That worked fine.
But as soon as try to do both I get a "no combination of intermediate filters could be found" error. I did several hours of deep digging into the media negotiation calls hitting my filter from the graph builder and then I found the problem. For some reason, the filter graph is dragging in the ancient "Indeo (R) Audio Software" codec into the chain.
I discovered this because despite the fact that codec did have a media format that matched my filter in almost every regard (major type, sub type, format type, wave format parameters), it had an extra 2 bytes at the end of it's pbFormat data member and that was enough to fail the equals test since that test does a comparison between the source and target pbFormat areas by comparing the cbFormat value of each media type. The Indeo codec has a cbFormat value of 20 while my filter has a cbFormat value of 18, which is the size of a _tWAVEFORMATEX data structure. In a way it's a good thing the Indeo pbFormat has that weird size because the first 18 bytes of its 20 byte area were exactly equal to the pbFormat area of my mixer filter's supported media type. Without that anomaly I never would have known that ancient codec was being drug in. I'm surprised it's being drug in at all since it has known exploits and vulnerabilities. What is most confusing is that this is happening on my mixer filter's output pin, not one of the input pins, and I have not made a single downstream connection yet when building up my pin connections.
Can anyone tell me why DirectShow is trying to drag in that codec despite the fact that the media formats for the both incoming filters, the Capture Filter and the Push Source filter, are identical and don't need any intermediate filters at all since they match my mixer filter's input pins supported format exactly? How can I fix this problem?
Also, I noticed that even in the single filter attachment tests above that succeeded, my mixer output pin was still getting queried for media formats. Why is that when as I said, at this point in building up my pin connections I have not connected anything to the output pin of my mixer filter?
--------------------------- UPDATE: 1 ----------------------------
I have learned that you can avoid the "intelligent connection" behavior entirely by using IFilterGraph.ConnectDirect() instead of IGraphBuilder.Connect(). I switched over to DirectConnect() and turns out that the input pin on my mixer filter is coming back as "already connected". That may be what is causing the graph builder to drag in the Indeo codec filter. Now that I have this new diagnostic information I will correct the problem and update this post with my results.
--------------------------- RESOLUTION ----------------------------
The root problem of all of this was my re-use of the input pin I obtained from the first destination/downstream filter I connected to my simple audio mixer filter, at the top of my application code. In other words my filter was working correctly, but I was not getting a fresh input pin with each upstream filter I tried to connect to it. Once I started doing that the connection process worked fine. I don't know why the code behind the IGraphBuilder.Connect() interface tried to bring in the Indeo codec filter, perhaps something to do with trying to connect to an already connected input pin, but it did. For my needs, I prefer the tight control that IFilterGraph.ConnectDirect() provides since it eliminates any interference from the intelligent connection code in IGraphBuilder, but I could see when video filters get involved it could become useful.

OpenCV with GigE Vision Cameras [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Closed 3 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I need to use OpenCV with a GigE Vision Ethernet Camera, but I couldn't find much useful information on how to do this, any pointers, documents and example code?
I need to read frames from the camera.
Gig-E is a communication standard for a wide range of cameras. OpenCV now contains a wrapper for The Prosilica Gig-E based cameras (see CV_CAP_PVAPI)
But in general it's better to use the camera's native API to get the data and then use openCV to convert the returned data into an image, openCv contains a number of Bayer pattern ->RGB routines.
The CvCapture module is convenient for testing, because it can seemlessly read from a camera or a file - but it's not really suitable for high-speed real-time vision
You can do this! I used the Baumer GAPI SDK, which is a GenTL consumer. GenTL is a generic transport layer, which is a module within genIcam. You can read up on GenTL HERE. Using a GenTL consumer like Baumer's GAPI or Basler's API makes things a lot easier. They should work with any GigE camera.
I made a more comprehensive way to use Baumer's GAPI SDK in another answer HERE, so I will give a summary of what you need.
Visual Studios
openCV 3 for C++ (HERE is a youtube tutorial on how)
Baumer GAPI SDK HERE
(optional) Test your camera and network interface card using Baumer's Camera Explorer program. You need to enable jumbo packets. You may also need to configure the camera and car IP address using Baumer's IPconfig program.
Setup your system Variables. refer to the programmer's guide in the Baumer GAPI SDK docs folder (should be in C:\Program Files\Baumer\Baumer GAPI SDK\Docs\Programmers_Guide). Refer to section 4.3.1.
Create a new C++ project in Visual Studios and configure the properties. Refer to section 4.4.1.
Go to the examples folder and look for 005_PixelTransformation example. It should be in (C:\Program Files\Baumer\Baumer GAPI SDK\Components\Examples\C++\src\0_Common\005_PixelTransformation). Copy the C++ file and paste it into the source directory of your new project.
Verify you can build and compile. NOTE: You may find a problem with the part that adjusts camera parameters (exposure time for example). you should see pixel values written to the screen for the first 6 pixels in the first 6 rows, for 8 images.
Add these #include statements to the top of the .cpp source file:
#include <opencv2\core\core.hpp
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\video\video.hpp>
Add these variable declarations at the beginning of the main() function
// OPENCV VARIABLE DECLARATIONS
cv::VideoWriter cvVideoCreator; // Create OpenCV video creator
cv::Mat openCvImage; // create an OpenCV image
cv::String videoFileName = "openCvVideo.avi"; // Define video filename
cv::Size frameSize = cv::Size(2048, 1088); // Define video frame size
cvVideoCreator.open(videoFileName, CV_FOURCC('D', 'I', 'V', 'X'), 20, frameSize, true); // set the codec type and frame rate
In the original 005_PixelTransformation.cpp file, line 569 has a for loop that loops over 8 images, which says for(int i = 0; i < 8; i++). We want to change this to run continuously. I did this by changing it to a while loop that says
while (pDataStream->GetIsGrabbing())
Within the while loop there's an if and else statement to check the image pixel format. After the else statement closing brace and before the pImage->Release(); statement, add the following lines
// OPEN CV STUFF
openCvImage = cv::Mat(pTransformImage->GetHeight(), pTransformImage->GetWidth(), CV_8U, (int *)pTransformImage->GetBuffer());
// create OpenCV window ----
cv::namedWindow("OpenCV window: Cam", CV_WINDOW_NORMAL);
//display the current image in the window ----
cv::imshow("OpenCV window : Cam", openCvImage);
cv::waitKey(1);
Make sure you chose the correct pixel format for your openCvImage object. I chose CV_8U because my camera is mono 8 bit.
When you build and compile, you should get an openCV window which displays the live feed from your camera!
Like I said, it can be done, because I've done it. If you run into problems, refer to the programmer's guide.
I use an uEye GigE camera (5240) with OpenCV. It works as a cv::VideoCapture out of the box. Nevertheless using the API allows for much more control over the cameras parameters.
You don't mention the type of the camera and your platform. On Windows, according to the OpenCV documentation:
Currently two camera interfaces can be
used on Windows: Video for Windows
(VFW) and Matrox Imaging Library (MIL)
It is unlikely that your GigE camera driver supports VFW, and for MIL you need the MIL library, which is not free AFAIK.
Most GigE cameras will have an API that you can use to capture images. In most cases the API will be based on GenICam. Probably your best approach is to use the API that came with your camera, and then convert the captured image to an IplImage structure (C) or Mat class (C++).

Resources