this code should ask 2 optional and 1 required argument, 'format' and 'type' argument are optional and 'url' is required argument which will be the address of website from where you wants to download image(either jpg or/and .png type image,depend on what value you give in 'type' argument ) and save it as either as individual image or single JSON file(depend on what value you give in 'format' argument ), i am getting error can you tell where i am going wrong,here is my code..
import argparse
import base64
import json
import os
from bs4 import BeautifulSoup
import requests
def scrape(url,format_,type_):
try:
page = requests.get(url)
except requests.RequestException as rex:
print(str(rex))
else:
soup = BeautifulSoup(url,'html.parser')
images = _fetch_images(soup,url)
images = _filter_images(images,type_)
_save(images,format_)
def _fetch_images(soup,base_url):
images = []
for img in soup.find_all('img'):
src = img.get('src')
img_url = ('{base_url}/{src}'.format(base_url,src))
name = img_url.split('\\')[-1]
images.append(dict(name=name,url=img_url))
return images
def _filter_images(images,type_):
if type == 'all':
return images
ext_map = {'png':['.png'],'jpg':['.jpg','.jpeg']}
return [img for img in images if
_match_extension(img['name'],ext_map(type_))]
def _match_extension(filename,extension_list):
name,extension = os.path.splittext(filename.lower())
return extension in extension_list
def _save(images,format_):
if images:
if format_=='img':
_save_images(images)
else:
_save_json(images)
print('Done!')
else:
print('there are no images!')
def _save_images(images):
for img in images:
img_data = requests.get(img['url']).content
with open(img['name'],'wb') as f:
f.write(img_data)
def _save_json(images):
data = {}
for img in images:
img_data = requests.get(img['url']).content
b64_img_data = base64.b64encode(img_data)
str_img_data = b64_img_data.decode('utf-8')
data[img['name']]=str_img_data
with open('images.json','w') as ijson:
ijson.write(json.dump(data))
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Scrape a webpage.')
parser.add_argument(
'-t',
'--type',
choices=['all', 'png', 'jpg'],
default='all',
help='The image type we want to scrape.')
parser.add_argument(
'-f',
'--format',
choices=['img', 'json'],
default='img',
help='The format images are saved to.')
parser.add_argument(
'url',
help='The URL we want to scrape for images.')
args = parser.parse_args()
args.url = str(input('enter the url\n'))
args.format = str(input('enter img or json \n'))
args.type = str(input('enter all or png or jpg'))
scrape(args.url,args.format,args.type)
i wants to run it in PyCharm and error i got is,
usage: scrape.py [-h] [-t {all,png,jpg}] [-f {img,json}] url
scrape.py: error: the following arguments are required: url
In order to pass parameters to your function in Pycharm, navigate to Run -> Edit Configurations and set the parameters there.
Alternatively, try invoking your program with parameters specified from the command line.
Related
I am making an image segmentation app which segments image into 'k' colors
the code for flask app goes like this:
##not pasting standard starting code
app.config['template_path'] = r'C:\Users\Asus\Documents\deep learning\deep_learn\NOTEBOOKS\app\templates'
def image_return():
if request.method == 'POST':
if request.files:
print('address accessed')
file = request.files['img']
k = request.values['k']
print('DONE FILE')
if not file.filename == '':
print('FILENAME EXISTS')
name = secure_filename(file.filename)
print(name)
address = os.path.join(
app.config['template_path'], 'uploads/', name)
file.save(address)
print('DONEEEE')
img = reader(address)
red_image, path = main(img, name, k)
print('image red. and saved to path')
return red_image, path
else:
redirect(request.url)
return flash('something went wrong try again')
# app.route('/transformed', methods=['POST'])
def transform():
red_image, path = image_return()
return render_template('imagetrans.html', address=path)
### ALL THE PRINT STATEMENTS RAN SUCCESSFULLY AND SAVED THE CONVERTED IMAGE TO THE PATH
## THE APPROACH I AM USING IS TO NOT DISPLAY LIVE IMAGE BUT TO SAVE IS FIRSTLY AND THEN DISPLAY IT FROM A SAVED LOCATION
the HTML goes like this:
<body>
<center>
<img src={{address}} alt="display.error" />
</center>
</body>
the python code for generating images works well
def color_reduction(img, k):
# transform the image
print(type(img))
data = np.float32(img).reshape((-1, 3))
# determine the criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 0.001)
# implementing k - means
ret, label, center = cv2.kmeans(
data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
center = np.uint8(center)
result = center[label.flatten()]
result = result.reshape(img.shape)
return result
template_path = r'C:\Users\Asus\Documents\deep learning\deep_learn\NOTEBOOKS\app\templates\transformed'
def main(img, filename, k=5, title=None):
red_image = color_reduction(img, k=int(k))
path = os.path.join(template_path, f'{filename}_{k}.jpg')
cv2.imwrite(path, red_image)
return red_image, path
the reduced_image is not read in img src even after passing correct variable address
I think I am going wrong at the HTML part!
Have you checked what the value for address is in the html, i.e. if you look at the page source what does the address value render as in your browser?
I think this is probably going wrong since it looks like you are passing an absolute filepath to the html whereas really you should pass a path that is relative to the flask app instance.
i.e. if your flask app is in a folder called my_site then to src you would just pass the path from my_site to the image, i.e. my_site\static\img\img.jpg rather than C:\Users\Documents\projects\my_site\static\img\img.jpg.
I know how to execute it via the command line, but looking for input to execute inside another python script. I tried passing the arguments as main(-- score-thr 0.7, --show, vid, config_file, chkpnt_file). Not sure that's how to do it though. Thank you in advance for helping out!
import argparse
import cv2
import mmcv
from mmdet.apis import inference_detector, init_detector
def parse_args():
parser = argparse.ArgumentParser(description='MMDetection video demo')
parser.add_argument('video', help='Video file')
parser.add_argument('config', help='Config file')
parser.add_argument('checkpoint', help='Checkpoint file')
parser.add_argument(
'--device', default='cuda:0', help='Device used for inference')
parser.add_argument(
'--score-thr', type=float, default=0.7, help='Bbox score threshold')
parser.add_argument('--out', type=str, help='Output video file')
parser.add_argument('--show', action='store_true', help='Show video')
parser.add_argument(
'--wait-time',
type=float,
default=1,
help='The interval of show (s), 0 is block')
args = parser.parse_args()
return args
def main():
args = parse_args()
assert args.out or args.show, \
('Please specify at least one operation (save/show the '
'video) with the argument "--out" or "--show"')
model = init_detector(args.config, args.checkpoint, device=args.device)
video_reader = mmcv.VideoReader(args.video)
video_writer = None
if args.out:
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video_writer = cv2.VideoWriter(
args.out, fourcc, video_reader.fps,
(video_reader.width, video_reader.height))
for frame in mmcv.track_iter_progress(video_reader):
result = inference_detector(model, frame)
frame = model.show_result(frame, result, score_thr=args.score_thr)
if args.show:
cv2.namedWindow('video', 0)
mmcv.imshow(frame, 'video', args.wait_time)
if args.out:
video_writer.write(frame)
if video_writer:
video_writer.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
main() gets its arguments from sys.argv when it uses argparse. So you need to fill that in before calling it.
sys.argv = ['progname.py', '--score-thr', '0.7', '--show', vid, config_file, chkpnt_file]
main()
I am trying to adapt some code to better suit my needs. The code currently takes all the files from a folder and runs image recognition on them, but I need to pass a single image that I specify from the command line.
Here is the code I am using:
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
# import the necessary packages
import json
import os
import random
import cv2 as cv
import keras.backend as K
import numpy as np
import scipy.io
from utils import load_model
if __name__ == '__main__':
img_width, img_height = 224, 224
model = load_model()
model.load_weights('models/model.96-0.89.hdf5')
cars_meta = scipy.io.loadmat('devkit/cars_meta')
class_names = cars_meta['class_names'] # shape=(1, 196)
class_names = np.transpose(class_names)
test_path = 'data/test/'
test_images = [f for f in os.listdir(test_path) if
os.path.isfile(os.path.join(test_path, f)) and f.endswith('.jpg')]
num_samples = 1
samples = random.sample(test_images, num_samples)
results = []
for i, image_name in enumerate(samples):
filename = os.path.join(test_path, image_name)
print('Start processing image: {}'.format(filename))
bgr_img = cv.imread(filename)
bgr_img = cv.resize(bgr_img, (img_width, img_height), cv.INTER_CUBIC)
rgb_img = cv.cvtColor(bgr_img, cv.COLOR_BGR2RGB)
rgb_img = np.expand_dims(rgb_img, 0)
preds = model.predict(rgb_img)
prob = np.max(preds)
class_id = np.argmax(preds)
text = ('Predict: {}, prob: {}'.format(class_names[class_id][0][0], prob))
results.append({'label': class_names[class_id][0][0], 'prob': '{:.4}'.format(prob)})
cv.imwrite('images/{}_out.png'.format(i), bgr_img)
print(results)
with open('results.json', 'w') as file:
json.dump(results, file, indent=4)
K.clear_session()
Is there a way that I can just pass a single image, instead of an entire folder, and do so from the command line?
sys.argv is a list in Python, which contains the command-line arguments passed to the script.
pay attention sys.argv[0] is the name of the script itself!
so the easieaset way to do it is by the built in sys.argv list. for example if my script is called : foo.py, i can pass to it arguments via command line like so:
python foo.py "C:\user\myimg.jpeg"
and in foo.py ican get the passed argument like so:
import sys
if __name__ == '__main__':
for arg in sys.argv[1:]:
#do work with arg! arg is a string type!
with open(arg) as fp:
#.... do work ....
argparse module
The following code is a Python program that takes a list of integers and produces either the sum or the max:
import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
const=sum, default=max,
help='sum the integers (default: find the max)')
args = parser.parse_args()
print(args.accumulate(args.integers))
using or calling from command line:
python foo.py 1 2 3 4
output: 4
python foo.py 1 2 3 4 --sum
10
New to python,
My professor has given me a piece of code to help process some imagery, however it only works one image at a time due to an input and output needing to be stipulated each time. Usually I would put import os or glob but argparse is something new to me and my usual methods do not work.
I need to edit this in order to create a list of '.hdf' files with the output being the same as the input just with a name change of '_Processed.hdf'
Code below:
# Import the numpy library
import numpy
# Import the GDAL library
from osgeo import gdal
# Import the GDAL/OGR spatial reference library
from osgeo import osr
# Import the HDF4 reader.
import pyhdf.SD
# Import the system library
import sys
# Import the python Argument parser
import argparse
import pprint
import rsgislib
def creatGCPs(lat_arr, lon_arr):
y_size = lat_arr.shape[0]
x_size = lat_arr.shape[1]
print(x_size)
print(y_size)
gcps = []
for y in range(y_size):
for x in range(x_size):
gcps.append([x, y, lon_arr[y,x], lat_arr[y,x]])
return gcps
def run(inputFile, outputFile):
hdfImg = pyhdf.SD.SD(inputFile)
#print("Available Datasets")
pprint.pprint(hdfImg.datasets())
#print("Get Header Attributes")
#attr = hdfImg.attributes(full=1)
#pprint.pprint(attr)
rsgisUtils = rsgislib.RSGISPyUtils()
wktStr = rsgisUtils.getWKTFromEPSGCode(4326)
#print(wktStr)
lat_arr = hdfImg.select('Latitude')[:]
long_arr = hdfImg.select('Longitude')[:]
sel_dataset_arr = hdfImg.select('Optical_Depth_Land_And_Ocean')[:]
gcplst = creatGCPs(lat_arr, long_arr)
y_size = lat_arr.shape[0]
x_size = lat_arr.shape[1]
min_lat = numpy.min(lat_arr)
max_lat = numpy.max(lat_arr)
min_lon = numpy.min(long_arr)
max_lon = numpy.max(long_arr)
lat_res = (max_lat-min_lat)/float(y_size)
lon_res = (max_lon-min_lon)/float(x_size)
driver = gdal.GetDriverByName( "KEA" )
metadata = driver.GetMetadata()
dst_ds = driver.Create( outputFile, x_size, y_size, 1, gdal.GDT_Float32 )
dst_ds.GetRasterBand(1).WriteArray(sel_dataset_arr)
gcp_list = []
for gcp_arr in gcplst:
gcp = gdal.GCP(int(gcp_arr[2]), int(gcp_arr[3]), int(0), gcp_arr[0], gcp_arr[1])
gcp_list.append(gcp)
dst_ds.SetGCPs(gcp_list, wktStr)
dst_ds = None
if __name__ == '__main__':
parser = argparse.ArgumentParser()
# Define the argument for specifying the input file.
parser.add_argument("-i", "--input", type=str, required=True, help="Specify the input image file.")
# Define the argument for specifying the output file.
parser.add_argument("-o", "--output", type=str, required=True, help="Specify the output image file.")
args = parser.parse_args()
run(args.input, args.output)
From the argparse docs here, you can simply add a nargs='*' to the argument definitions. However, be sure to give the input and output files in the same order...
Also, you can use the pathlib.Path object, which is now standard in Python >=3.4, to play with file names.
So with an added from pathlib import Path at the top, the last part of your code becomes:
if __name__ == '__main__':
parser = argparse.ArgumentParser()
# Define the argument for specifying the input file.
parser.add_argument("-i", "--input", nargs='*', type=str, required=True, help="Specify the input image file.")
args = parser.parse_args()
for input in args.input:
output = Path(input).stem + '_Processed.hdf'
run(input, output)
Here, args.input is now a list of strings, so we iterate on it. The .stem attribute returns the file name without any extensions, I find it cleaner than something like input[:-4], which only works for specific extension lengths...
This works well with glob patterns in a standard linux shell (I don't know for other cases).
Ex. calling python this_script.py -i Image_*, processes every file with filenames beginning with "Image_".
You can use the nargs='+' option, and since you're going to have only have one required argument, I'd recommend that you don't use --input as an option, but simply run the script as script_name.py input_file1 input_file2 input_file3 ...:
import os.path
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('input', nargs='+', help="Specify the input image file.")
args = parser.parse_args()
for filename in args.input:
root, ext = os.path.splitext(filename)
run(filename, ''.join((root, '_Processed', ext)))
I am learning Python through the development of a Kodi add-on. I am trying to display an image using the xbmcplugin.setResolvedUrl() function but I get an error:
'Attempt to use invalid handle -1' error.
I am get rid of the error when including li.setProperty("IsPlayable", "true") in my addFile function but then the image is not displayed.
What am I doing wrong?
My code:
import sys
import urllib
import urlparse
import xbmcgui
import xbmcplugin
import xbmcaddon
my_addon = xbmcaddon.Addon()
addon_path = xbmc.translatePath(my_addon.getAddonInfo('path'))
base_url = sys.argv[0]
addon_handle = int(sys.argv[1])
args = urlparse.parse_qs(sys.argv[2][1:])
mode = args.get('mode', None)
def build_url(query):
return base_url + '?' + urllib.urlencode(query)
def addFile(filename, filepath):
filedir = build_url({'mode': 'display', 'filepath': filepath})
li = xbmcgui.ListItem(filename)
xbmcplugin.addDirectoryItem(handle=addon_handle, url=filedir, listitem=li)
def displayImage(url):
li = xbmcgui.ListItem('Sample image')
li.setPath(url)
xbmcplugin.setResolvedUrl(addon_handle, True, listitem=li)
xbmc.log('Display image...',level=xbmc.LOGNOTICE)
if mode is None:
fileurl = 'https://elmicrolector.files.wordpress.com/2016/10/breu-14-a1.jpg'
addFile('Sample image', fileurl)
xbmcplugin.setContent(addon_handle, 'files')
xbmcplugin.endOfDirectory(addon_handle)
elif mode[0] == 'display':
displayImage(args['filepath'][0])
I found out the xbmcplugin.setResolvedUrl() function can only be used with videos, not with images.