Why wls_filter generate white flash - python-3.x

I am using opencv 3.4 and python 3.
I have a real-time video from an usb stereo camera with which I performed SGBM stereo match and then I applied a wls filter as following:
#setting filter parameters
lmbda = 80000
sigma = 1.2
visual_multiplier = 1.0
wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=stereoMatcher)
wls_filter.setLambda(lmbda)
wls_filter.setSigmaColor(sigma)
# # Using the WLS filter
np.uint8(dispL)
filteredImg= wls_filter.filter(dispL,grayLeft,None,dispR)
filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg, beta=1, alpha=255, norm_type=cv2.NORM_MINMAX);
The video I obtain is quite good, but the problem is that I receive frames of video which are totally white, like flesh in the image.
Why does this happen and there is a way to avoid it?

I had the same issue as well. I used the default wls filter by cv.ximgproc.createDisparityWLSFilterGeneric(False) instead. It gave me a proper result but not ideal.

Related

Compare images for finding the images are visibly same

Need to find the images are same , even if it has different resolution and size. No need of a pixel to pixel comparison, need to find all the images , texts, color etc. are same in the other image also.
Tried with different python packages to compare, but all are asking for same resolution. One of my image is screenshotted from Mac and other is from Ubuntu. Even both are same html, the contrast and resolution difference of the machines causing the images to become different when compare.
Tried.
Perceptual diff,
Image Hash etc.
• PDIFFER – Python wrapper for perceptualdiff tool (https://pypi.org/project/pdiffer/)
Problem - pip install pdiffer failed to install in the Macs for the latest as well as old versions
• NEEDLE - Installed needle (https://needle.readthedocs.io/en/latest/) This one has an option to specify comparison engine to be perceptualdiff/Imagemagick instead of default PIL.
Problem Found - Has an option to save baseline image first and then run assertions on them. It works when baseline is saved and then compared. I didn’t find anything that would compare the screenshots with existing images.
• OPENCV – Histogram based comparison. This converts images into grayscale, and into histograms and compares the histograms. Returns a value between -1 and 1 (-1 means not similar at all and 1 means highly similar) (https://www.pyimagesearch.com/2014/07/14/3-ways-compare-histograms-using-opencv-python/ )
Findings - I tested two images by converting into histograms and compared them Which returned a value of 0.8 (meaning somewhat similar).
Below code i tried using imagehash:
from PIL import Image import imagehash
image_one = 'result.png'
img = Image.open(image_one) image_one_hash = imagehash.whash(img)
print(image_one_hash)
image_two = 'not-found-02.png'
img2 = Image.open(image_two) image_two_hash = imagehash.whash(img2)
print(image_two_hash)
similarity = image_one_hash - image_two_hash print(similarity)

How to differentiate Passport and PAN card Scanned images in python

The goal is to identify that the input scanned image is passport or PAN card using Opencv.
I have used structural_similarity(compare_ssim) method of skimage to compare input scan image with the images of template of Passport and PAN card.
But in both cases i got low score.
Here is the code that i have tried
from skimage.measure import compare_ssim as ssim
import matplotlib.pyplot as plt
import numpy as np
import cv2enter code here
img1 = cv2.imread('PAN_Template.jpg', 0)
img2 = cv2.imread('PAN_Sample1.jpg', 0)
def prepare_img(im):
size = 300, 200
im = cv2.resize(im, size)
return im
img1 = prepare_img(img1)
img2 = prepare_img(img2)
def compare_images(imageA, imageB):
s = ssim(imageA, imageB)
return s
ssim = compare_images(img1, img2)
print(ssim)
Comparing the PAN Card Template with Passport i have got ssim score of 0.12
and Comparing the PAN Card template with a PAN Card the score was 0.20
Since both the score were very close i wast not able to distinguish between them through the code.
If anyone got any other solution or approach then please help.
Here is a sample image
PAN Scanned Image
You can also compare 2 images by the mean square error (MSE) of those 2 images.
def mse(imageA, imageB):
# the 'Mean Squared Error' between the two images is the
# sum of the squared difference between the two images;
# NOTE: the two images must have the same dimension
err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
err /= float(imageA.shape[0] * imageA.shape[1])
# return the MSE, the lower the error, the more "similar"
# the two images are
return err
As per my understanding Pan card and Passport images contain different text data, so i believe OCR can solve this problem.
All you need to do is- extract the text data from the images using any OCR library like Tesseract and look for a few predefined key words in the text data to differentiate the images.
Here is simple Python script showing the image pre-processing and OCR using pyteseract module:
img = cv2.imread("D:/pan.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,th1 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv2.imwrite('filterImg.png', th1)
pilImg = Image.open('filterimg.png')
text = pytesseract.image_to_string(pilImg)
print(text.encode("utf-8"))
Below is the binary image used for OCR:
I got the below string data after doing the OCR on the above image:
esraax fram EP aca ae
~ INCOME TAX DEPARTMENT Ld GOVT. OF INDIA
wrtterterad sg
Permanent Account Number. Card \xe2\x80\x98yf
KFWPS6061C
PEF vom ; ae
Reviavs /Father's Name. e.
SUDHIR SINGH : . ,
Though this text data contains noises but i believe it is more than enough to get the job done.
Another OCR solution is to use TextCleaner ImageMagick script from Fred's Scripts. A tutorial which explain how to install and use it (on Windows) is available here.
Script used:
C:/cygwin64/bin/textcleaner -g -e normalize -f 20 -o 20 -s 20 C:/Users/Link/Desktop/id.png C:/Users/Link/Desktop/out.png
Result:
I applied OCR on this with Tesseract (I am using version 4) and that's the result:
fart
INCOME TAX DEPARTMENT : GOVT. OF INDIA
wort cra teat ears -
Permanent Account Number Card
KFWPS6061C
TT aa
MAYANK SUDHIR SINGH el
far aT ary /Father's Name
SUDHIR SINGH
Wa RT /Date of Birth den. +
06/01/1997 genge / Signature
Code for OCR:
import cv2
from PIL import Image
import tesserocr as tr
number_ok = cv2.imread("C:\\Users\\Link\\Desktop\\id.png")
blur = cv2.medianBlur(number_ok, 1)
cv2.imshow('ocr', blur)
pil_img = Image.fromarray(cv2.cvtColor(blur, cv2.COLOR_BGR2RGB))
api = tr.PyTessBaseAPI()
try:
api.SetImage(pil_img)
boxes = api.GetComponentImages(tr.RIL.TEXTLINE, True)
text = api.GetUTF8Text()
finally:
api.End()
print(text)
cv2.waitKey(0)
Now, this don't answer at your question (passport or PAN card) but it's a good point where you can start.
Doing OCR might be a solution for this type of image classification but it might fail for the blurry or not properly exposed images. And it might be slower than newer deep learning methods.
You can use Object detection (Tensorflow or any other library) to train two separate class of image i.e PAN and Passport. For fine-tuning pre-trained models, you don't need much data too. And as per my understanding, PAN and passport have different background color so I guess it will be really accurate.
Tensorflow Object Detection: Link
Nowadays OpenCV also supports object detection without installing any new libraries(i.e.Tensorflow, caffee, etc.). You can refer this article for YOLO based object detection in OpenCV.
We can use:
Histogram Comparison - Simplest & fastest methods, using this we will get the similarity between histograms.
Template Matching - Searching and finding the location of a template image, using this we can find smaller image parts in a bigger one. (like some common patterns in PAN card).
Feature Matching - Features extracted from one image and the same feature will be recognised in another image even if the image rotated or skewed.

Adding watermark to video

I am able to use the moviepy library to add a watermark to a section of video. However when I do this it is taking the watermarked segment, and creating a new file with it. I am trying to figure out if it is possible to simply splice in the edited part back into the original video, as moviepy is EXTREMELY slow writing to the disk, so the smaller the segment the better.
I was thinking maybe using shutil?
video = mp.VideoFileClip("C:\\Users\\admin\\Desktop\\Test\\demovideo.mp4").subclip(10,20)
logo = (mp.ImageClip("C:\\Users\\admin\\Desktop\\Watermark\\watermarkpic.png")
.set_duration(20)
.resize(height=20) # if you need to resize...
.margin(right=8, bottom=8, opacity=0) # (optional) logo-border padding
.set_pos(("right","bottom")))
final = mp.CompositeVideoClip([video, logo])
final.write_videofile("C:\\Users\\admin\\Desktop\\output\\demovideo(watermarked).mp4", audio = True, progress_bar = False)
Is there a way to copy the 10 second watermarked snippet back into the original video file? Or is there another library that allows me to do this?
What is slow in your use case is the fact that Moviepy needs to decode and reencode each frame of the movie. If you want speed, I believe there are ways to ask FFMPEG to copy video segments without rencoding.
So you could use ffmpeg to cut the video into 3 subclips (before.mp4/fragment.mp4/after.mp4), only process fragment.mp4, then reconcatenate all clips together with ffmpeg.
The cutting into 3 clips using ffmpeg can be done from moviepy:
https://github.com/Zulko/moviepy/blob/master/moviepy/video/io/ffmpeg_tools.py#L27
However for concatenating everything together you may need to call ffmpeg directly.

Raspberry Pi use Webcam instead of PiCam

Here is the code to initialize raspberry camera by pyimagesearch blog.I want to add a webcam to capture frame by frame in
camera = PiCamera()
camera.resolution = tuple(conf["resolution"])
camera.framerate = conf["fps"]
rawCapture = PiRGBArray(camera, size=tuple(conf["resolution"]))
for f in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
# grab the raw NumPy array representing the image and initialize
# the timestamp and occupied/unoccupied text
frame = f.array
This is the part that continuously captures frames from PiCamera. The problem is that I want to read frame by frame from webcam too. I somehow got it working, But lost the code accidentally. Now I don't remember what did I do. I got it working in just about 2-3 extra lines. Please help me get it if you can. Thank you.

How to capture still image from webcam on linux

I am trying to write a C++/Qt program for linux, where I take a still image photo from a webcam, make some transformations to a photo (cropping, resizing, etc.), and save it to a jpeg file.
But I have encountered some problems. The main problem is that standart UVC (usb video device class) linux driver currently does not support direct still image capture: http://www.ideasonboard.org/uvc/ .
So, there are two possible ways to capture still image. You can take one frame from the video stream from the camera, or you can take a separate photo, like a digital portable camera. The second way is not supported in linux uvc driver, so the first method is the only way. But the problem is, that if you want to take a frame from the video stream, the size of the photo can't be bigger than the size of video in the video preview window. So, if I want to take 2 megapixel photo, I must start videostream with the size 1600x1200, which is not so comfortable (At least, in Qt the size of the videostream depends on the videopreview window size).
I know that there is video for linux 2 API, which may be helpful in this task, but I don't know how to use it. I am currently learning gstreamer, but I can't now figure out how to do what I need using these tools.
So, I will appreciate any help. I think it is not a hard problem for people who know Linux, GStreamer, v4l2 API, and other linux-specific things.
By the way, the program will be used only with web-camera Logitech C270 HD.
Please, help me. I don't know what API or framework can help me do this. May be you know.
Unfortunately the C4V2 calls in opencv did not work for still image capture with any camera I have tried out of the box using the UVC driver.
To debug the issue I have been playing with trying to accomplish this with c code calling c4v2 directly.
I have been playing with the example code found here. It uses the method of pulling frames from the video stream.
You can compile it with:
gcc -O2 -Wall `pkg-config --cflags --libs libv4l2` filename.c -o filename
I have experimented with 3 logitech cameras. The best of the lot seems to be the Logitech C910. But even it has significant issues.
Here are the problems I have encountered trying to accomplish your same task with this code.
It works pretty much every time with width and height set to 1920x1080.
When I query other possibilities directly from the command line using for example:
v4l2-ctl --list-formats-ext
and I try some of the other "available" smaller sizes it hangs in the select waiting for the camera to release the buffer.
Also when I try to set other sizes directly from the command line using for example:
v4l2-ctl -v height=320 -v width=240 -v pixelformat=YUYV
Then check with
v4l2-ctl -V
I find that it returns the correct pixel format but quite often not the correct size.
Apparently this camera which is listed on the UVC site as being UVC and therefore v4l2 compatible is not up to snuff. I suspect it is just as bad for other cameras. The other two I tried were also listed as compatible on the site but had worse problems.
I did some more testing on the LogitechC910 after I posted this. I thought I would post the results in case it helps someone else out.
I wrote a script to test v4l2 grabber code mentioned above on all the formats the camera claims it supports when it is queried with v4l2 here are the results:
640x480 => Hangs on clearing buffer
160x120 => Works
176x144 => Works
320x176 => Works
320x240 => Works
432x240 => Works
352x288 => Works
544x288 => Works
640x360 => Works
752x416 => Hangs on clearing buffer
800x448 => Hangs on clearing buffer
864x480 => Works
960x544 => Works
1024x576 => Works
800x600 => Works
1184x656 => Works
960x720 => Works
1280x720 => Works
1392x768 => Works
1504x832 => Works
1600x896 => Works
1280x960 => Works
1712x960 => Works
1792x1008 => Works
1920x1080 => Works
1600x1200 => Works
2048x1536 => Works
2592x1944 => Hangs on clearing buffer.
It turns out that the default setting of 640x480 doesnt work and that is what trapped me and most others who have posted on message boards.
Since it is grabbing a video frame the first frame it grabs when starting up may have incorrect exposure (often black or close to it). I believe this is because since it is being used as a video camera it adjusts exposure as it goes and doesnt care about the first frames. I believe this also trapped me and other who saw the first frame as black or nearly black and thought it was some kind of error. Later frames have the correct exposure
It turns out that opencv with python wrappers works fine with this camera if you avoid the land mines listed above and ignore all the error messages. The error messages are due to the fact while the camera accepts v4l2 commands it doesnt respond correctly. So if you set the width it actually gets set correctly but it responds with an incorrect width.
To run under opencv with python wrappers you can do the following:
import cv2
import numpy
cap = cv2.VideoCapture(0) #ignore the errors
cap.set(3, 960) #Set the width important because the default will timeout
#ignore the error or false response
cap.set(4, 544) #Set the height ignore the errors
r, frame = cap.read()
cv2.imwrite("test.jpg", frame)
**Download And Install 'mplayer'**
mplayer -vo png -frames 1 tv://
mplayer -vo png -frames 1 tv://
might give a green screen output as the camera is not yet ready.
mplayer -vo png -frames 2 tv://
You can try increasing the number of frames and choose a number from which the camera gives correct images.
What about this program?
#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
VideoCapture webcam;
webcam.open(0);
Mat frame;
char key;
while(true)
{
webcam >> frame;
imshow("My Webcam",frame);
key = waitKey(10);
if(key=='s')
break;
}
imwrite("webcam_capture.jpg", frame);
webcam.release();
return 0;
}
This will capture a picture of maximum size allowed by your webcam. Now you can add effects or resize the captured image with Qt. And OpenCV is very very easy to integrate with Qt, :)

Resources