I used Open CV to get the Image Difference using Python and code doesn't work - python-3.x

I am using Python 3.6.2. I am looking to run this code https://www.pyimagesearch.com/2017/06/19/image-difference-with-opencv-and-python/, but I have received this error:
usage: [-h] -f FIRST -s SECOND
error: the following arguments are required: -f/--first, -s/--second"
when I run the last line of this code and I don't know what is wrong:
from skimage.measure import compare_ssim
import argparse
import imutils
import cv2
import args
ap = argparse.ArgumentParser()
ap.add_argument("-f", "--first", required=True,default='I:\Aaron - Satslab\Pyimagesearch - code - Image processing and computer vision and others\image-difference\images\first.png',
help="firstinputimage")
ap.add_argument("-s", "--second", required=True,default='I:\Aaron - Satslab\Pyimagesearch - code - Image processing and computer vision and others\image-difference\images\second.png',
help="second")
args = vars(ap.parse_args())
Looking forward to your help.

The problem is that you added a default value to the arguments you add, but didn't set required=False. This means the program will throw an exception when parsing the arguments, unless you invoke it with the actual -f/--first and -s/--second.
The solution is to either:
Set required=False in both add_argument calls, since you provide a default. That way, you can call python my_script.py and it will use the default provided.
Invoke your program by providing the two CLI options: python my_script. py -f some_file.png -s some_other_file.png

Related

Why there is a permisson denied error while using node-tesseract-ocr?

I am using node-tesseract-ocr library for using ocr for my node js project. I installed tesseract-ocr in my machine(windows) using choco and then node-tesseract-ocr using npm. While requesting that particular route I am getting the following error
Error, cannot read input file "myActualPath": Permission denied
Error during processing.
This is the code I am using
const config = {
lang: 'eng',
oem: 1,
psm: 3,
};
tesseract
.recognize(__dirname, `../public/data/${reciept}`, config)
.then((text) => {
serialResponse = text.match(new RegExp(serial, 'g'));
})
.catch((error) => {
console.log(error.message);
});
Make sure you have added the tesseract-OCR path in your environment variables, and restart your IDE
Note, for programs like PyCharm and many others, you need to also close the program and re-open it after setting the system environment variable - As told by silas in another post similar to this one.
You can refer that post here .
Make sure to import the necessary packages in your module
import pytesseract
import argparse
import cv2
Then construct the argument parser and parse the arguments.
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image to be OCR'd")
args = vars(ap.parse_args())
Note The first Python import you’ll notice in this script is pytesseract (Python Tesseract), a Python binding that ties in directly with the Tesseract OCR application running on your system. The power of pytesseract is our ability to interface with Tesseract rather than relying on ugly os.cmd calls as we needed to do before pytesseract ever existed.
For additional reference.

JupyterLab 3: how to get the list of running servers

Since JupyterLab 3.x jupyter-server is used instead of the classic notebook server, and the following code does not list servers served with jupyter_server:
from notebook import notebookapp
notebookapp.list_running_servers()
None
What still works for the file/notebook name is:
from time import sleep
from IPython.display import display, Javascript
import subprocess
import os
import uuid
def get_notebook_path_and_save():
magic = str(uuid.uuid1()).replace('-', '')
print(magic)
# saves it (ctrl+S)
# display(Javascript('IPython.notebook.save_checkpoint();')) # Javascript Error: IPython is not defined
nb_name = None
while nb_name is None:
try:
sleep(0.1)
nb_name = subprocess.check_output(f'grep -l {magic} *.ipynb', shell=True).decode().strip()
except:
pass
return os.path.join(os.getcwd(), nb_name)
But it's not pythonic nor fast
How to get the current running server instances - and so e.g. the current notebook file?
Migration to jupyter_server should be as easy as changing notebook to jupyter_server, notebookapp to serverapp and changing the appropriate configuration files - the server-related codebase is largely unchanged. In the case of listing servers simply use:
from jupyter_server import serverapp
serverapp.list_running_servers()

Hi, I'm trying to use argparse in python as given code below, [duplicate]

Using argparse in a Jupyter Notebook throws a TypeError. The same code works fine if I execute the same code as a script. MWE:
import argparse
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('--name', '-n', default='foo', help='foo')
args = parser.parse_args()
Result:
TypeError: 'level' is an invalid keyword argument for this function
One solution is to parse an empty list of arguments:
import argparse
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('--name', '-n', default='foo', help='foo')
args = parser.parse_args([])
Another is to use parse_known_args:
args, _ = parser.parse_known_args()
Ipython is running some command-line arguments in the background. This interfers with argparse and optparse.
See this bug for Spyder (Ipython IDE), where -f was being added as a command option and crashing as there was no handler for -f.
You could try checking the arguments currently in play (as they did for the Spyder bug) and putting a dummy handler in place.
Run
import sys
print(sys.argv)
inside Ipython and see what it outputs.
On my system, it gives
['/usr/lib/python3.6/site-packages/ipykernel_launcher.py', '-f', '/run/user/1000/jupyter/kernel-7537e4dd-b5e2-407c-9d4c-7023575cfc7c.json']
Argparse assumes the first entry is the program name (sys.argv[0]). In order to fix this, I had to call
parser = argparse.ArgumentParser(prog='myprogram', description='Foo')
... and now argparse works in my notebook.
When I run your code in a Notebook, I get an argparse usage error message:
usage: ipykernel_launcher.py [-h] [--name NAME]
ipykernel_launcher.py: error: unrecognized arguments: -f /run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json
With a print(sys.argv) I get
['/home/paul/.local/lib/python3.6/site-packages/ipykernel_launcher.py', '-f', '/run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json']
sys.argv, which parser parses, contains the values used to launch the Notebook server, which this particular parser is not setup to handle.
parser.parse_known_args() displays:
(Namespace(name='foo'),
['-f',
'/run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json'])
That extra stuff that your parser can't handle is put in the extras list.
Run with a custom argv list works:
parser.parse_args(['-n', 'foobar'])
Namespace(name='foobar')
It's a good idea to put argparse code (at least the parse_args line) in a __main__ block, so it is not run when the script is imported. It will still run when the script is run as a script.
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('--name', '-n', default='foo', help='foo')
args = parser.parse_args()
print(args)
This script also works when using %run stack50763033.py. You can even give it arguments as you would with a script:
%run stack50763033.py -n testing
I have no idea what code is producing the level keyword error. You'll have to give us the traceback if you want help with that.

PytestUnknownMarkWarning: Unknown pytest.mark.xxx - is this a typo?

I have a file called test.py with the following code:
import pytest
#pytest.mark.webtest
def test_http_request():
pass
class TestClass:
def test_method(self):
pass
pytest -s test.py passed but gave the following warnings:
pytest -s test.py
=============================== test session starts ============================
platform linux -- Python 3.7.3, pytest-5.2.4, py-1.8.0, pluggy-0.13.1
rootdir: /home/user
collected 2 items
test.py ..
=============================== warnings summary ===============================
anaconda3/lib/python3.7/site-packages/_pytest/mark/structures.py:325
~/anaconda3/lib/python3.7/site-packages/_pytest/mark/structures.py:325:
PytestUnknownMarkWarning: Unknown pytest.mark.webtest - is this a typo? You can register
custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.html
PytestUnknownMarkWarning,
-- Docs: https://docs.pytest.org/en/latest/warnings.html
=============================== 2 passed, 1 warnings in 0.03s ===================
Environment: Python 3.7.3, pytest 5.2.4, anaconda3
What is the best way to get rid of the warning message?
To properly handle this you need to register the custom marker. Create a pytest.ini file and place the following inside of it.
[pytest]
markers =
webtest: mark a test as a webtest.
Next time you run the tests, the warning about the unregistered marker will not be there.
without updating pytest.ini, we can ignore warning using --disable-warnings
We can also use --disable-pytest-warnings
Example using your case:
pytest -s test.py -m webtest --disable-warnings
#gold_cy's answer works. If you have too many custom markers need to register in pytest.ini, an alternative way is to use the following configuration in pytest.ini:
[pytest]
filterwarnings =
ignore::UserWarning
or in general, use the following:
[pytest]
filterwarnings =
error
ignore::UserWarning
the configuration above will ignore all user warnings, but will transform all other warnings into errors. See more at Warnings Capture
test.py (updated with two custom markers)
import pytest
#pytest.mark.webtest
def test_http_request():
print("webtest::test_http_request() called")
class TestClass:
#pytest.mark.test1
def test_method(self):
print("test1::test_method() called")
Use the following commands to run desired tests:
pytest -s test.py -m webtest
pytest -s test.py -m test1
The best way to get rid of the message is to register the custom marker as per #gold_cy's answer.
However if you just wish to suppress the warning as per Jonathon's answer, rather than ignoring UserWarning (which will suppress all instances of the warning regardless of their source) you can specify the particular warning you want to suppress like so (in pytest.ini):
ignore::_pytest.warning_types.PytestUnknownMarkWarning
Note: For third party libraries/modules the full path to the warning is required to avoid an _OptionError exception
If you don't have pytest.ini and don't wanna create one just for this then you can also register it programmatically in conftest.py as described here:
def pytest_configure(config):
# register an additional marker
config.addinivalue_line(
"markers", "env(name): mark test to run only on named environment"
)
To add to the existing answers - custom markers can also be registered in pyproject.toml:
# pyproject.toml
[tool.pytest.ini_options]
markers = [
"webtest: mark a test as a webtest.",
]
Related docs.

ipython notebook --script deprecated. How to replace with post save hook?

I have been using "ipython --script" to automatically save a .py file for each ipython notebook so I can use it to import classes into other notebooks. But this recenty stopped working, and I get the following error message:
`--script` is deprecated. You can trigger nbconvert via pre- or post-save hooks:
ContentsManager.pre_save_hook
FileContentsManager.post_save_hook
A post-save hook has been registered that calls:
ipython nbconvert --to script [notebook]
which behaves similarly to `--script`.
As I understand this I need to set up a post-save hook, but I do not understand how to do this. Can someone explain?
[UPDATED per comment by #mobius dumpling]
Find your config files:
Jupyter / ipython >= 4.0
jupyter --config-dir
ipython <4.0
ipython locate profile default
If you need a new config:
Jupyter / ipython >= 4.0
jupyter notebook --generate-config
ipython <4.0
ipython profile create
Within this directory, there will be a file called [jupyter | ipython]_notebook_config.py, put the following code from ipython's GitHub issues page in that file:
import os
from subprocess import check_call
c = get_config()
def post_save(model, os_path, contents_manager):
"""post-save hook for converting notebooks to .py scripts"""
if model['type'] != 'notebook':
return # only do this for notebooks
d, fname = os.path.split(os_path)
check_call(['ipython', 'nbconvert', '--to', 'script', fname], cwd=d)
c.FileContentsManager.post_save_hook = post_save
For Jupyter, replace ipython with jupyter in check_call.
Note that there's a corresponding 'pre-save' hook, and also that you can call any subprocess or run any arbitrary code there...if you want to do any thing fancy like checking some condition first, notifying API consumers, or adding a git commit for the saved script.
Cheers,
-t.
Here is another approach that doesn't invoke a new thread (with check_call). Add the following to jupyter_notebook_config.py as in Tristan's answer:
import io
import os
from notebook.utils import to_api_path
_script_exporter = None
def script_post_save(model, os_path, contents_manager, **kwargs):
"""convert notebooks to Python script after save with nbconvert
replaces `ipython notebook --script`
"""
from nbconvert.exporters.script import ScriptExporter
if model['type'] != 'notebook':
return
global _script_exporter
if _script_exporter is None:
_script_exporter = ScriptExporter(parent=contents_manager)
log = contents_manager.log
base, ext = os.path.splitext(os_path)
py_fname = base + '.py'
script, resources = _script_exporter.from_filename(os_path)
script_fname = base + resources.get('output_extension', '.txt')
log.info("Saving script /%s", to_api_path(script_fname, contents_manager.root_dir))
with io.open(script_fname, 'w', encoding='utf-8') as f:
f.write(script)
c.FileContentsManager.post_save_hook = script_post_save
Disclaimer: I'm pretty sure I got this from SO somwhere, but can't find it now. Putting it here so it's easier to find in future (:
I just encountered a problem where I didn't have rights to restart my Jupyter instance, and so the post-save hook I wanted couldn't be applied.
So, I extracted the key parts and could run this with python manual_post_save_hook.py:
from io import open
from re import sub
from os.path import splitext
from nbconvert.exporters.script import ScriptExporter
for nb_path in ['notebook1.ipynb', 'notebook2.ipynb']:
base, ext = splitext(nb_path)
script, resources = ScriptExporter().from_filename(nb_path)
# mine happen to all be in Python so I needn't bother with the full flexibility
script_fname = base + '.py'
with open(script_fname, 'w', encoding='utf-8') as f:
# remove 'In [ ]' commented lines peppered about
f.write(sub(r'[\n]{2}# In\[[0-9 ]+\]:\s+[\n]{2}', '\n', script))
You can add your own bells and whistles as you would with the standard post save hook, and the config is the correct way to proceed; sharing this for others who might end up in a similar pinch where they can't get the config edits to go into action.

Resources