PyQt6 adding image resource to QDocument - qtextedit

I am porting an application from PyQT5 to PyQt6. It displays multiple images in a QTextEdit. I need to add an image resource to QTextEdit QTextDocument but am getting an error.
TypeError: addResource(self, int, QUrl, Any): argument 1 has unexpected type 'ResourceType'
Method variables are img: Dictionary, counter: Integer, text_edit: QTextEdit
path_ = self.app.project_path
if img['mediapath'][0] == "/":
path_ = path_ + img['mediapath']
else:
path_ = img['mediapath'][7:]
document = text_edit.document()
image = QtGui.QImageReader(path_).read()
image = image.copy(img['x1'], img['y1'], img['width'], img['height'])
# Need unique image names or the same image from the same path is reproduced
imagename = self.app.project_path + '/images/' + str(counter) + '-' + img['mediapath']
url = QtCore.QUrl(imagename)
document.addResource(QtGui.QTextDocument.ResourceType.ImageResource, url, QtCore.QVariant(image))
The Qt6 documentation at https://doc.qt.io/qt-6/qtextdocument.html#addResource says:
For example, you can add an image as a resource in order to reference it from within the document:
document->addResource(QTextDocument::ImageResource,
QUrl("mydata://image.png"), QVariant(image));
Note: I have tried the following which matches the Qt6 documentation:
document.addResource(QtGui.QTextDocument.ImageResource, url, QtCore.QVariant(image))
This gives the error: AttributeError: type object 'QTextDocument' has no attribute 'ImageResource'

I found a solution that works, and I think, either the QT6 documentation needs to be updated, or the PyQt6 implementation of the documentation needs to be developed.
The required Integer is stored in the value attribute:
document.addResource(QtGui.QTextDocument.ResourceType.ImageResource.value, url, QtCore.QVariant(image))
QVariant method is not required, simpler code below:
document.addResource(QtGui.QTextDocument.ResourceType.ImageResource.value, url, image)

Related

AWS Sagemaker custom PyTorch model inference on raw image input

I am new to AWS Sagemaker. I have custom CV PyTorch model locally and deployed it to Sagemaker endpoint. I used custom inference.py code to define model_fn, input_fn, output_fn and predict_fn methods. So, I'm able to generate predictions on json input, which contains url to the image, the code is quite straigtforward:
def input_fn(request_body, content_type='application/json'):
logging.info('Deserializing the input data...')
image_transform = transforms.Compose([
transforms.Resize(size=(224, 224)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
if content_type:
if content_type == 'application/json':
input_data = json.loads(request_body)
url = input_data['url']
logging.info(f'Image url: {url}')
image_data = Image.open(requests.get(url, stream=True).raw)
return image_transform(image_data)
raise Exception(f'Requested unsupported ContentType in content_type {content_type}')
Then I am able to invoke endpoint with code:
client = boto3.client('runtime.sagemaker')
inp = {"url":url}
inp = json.loads(json.dumps(inp))
response = client.invoke_endpoint(EndpointName='ENDPOINT_NAME',
Body=json.dumps(inp),
ContentType='application/json')
The problem is, I see, that locally url request return slightly different image array comparing to the one on Sagemaker. Which is why on the same URL I obtain slightly different predictions. To check that at least model weights are the same I want to generate predictions on image itself, downloaded locally and to Sagemaker. But I fail trying to put image as input to endpoint. E.g.:
def input_fn(request_body, content_type='application/json'):
logging.info('Deserializing the input data...')
image_transform = transforms.Compose([
transforms.Resize(size=(224, 224)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
if content_type == 'application/x-image':
image_data = request_body
return image_transform(image_data)
raise Exception(f'Requested unsupported ContentType in content_type {content_type}')
Invoking endpoint I experience the error:
ParamValidationError: Parameter validation failed:
Invalid type for parameter Body, value: {'img': <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=630x326 at 0x7F78A61461D0>}, type: <class 'dict'>, valid types: <class 'bytes'>, <class 'bytearray'>, file-like object
Does anybody know how to generate Sagemaker predictions by Pytorch model on images?
As always, after asking I found a solution. Actually, as the error suggested, I had to convert input to bytes or bytearray. For those who may need the solution:
from io import BytesIO
img = Image.open(open(PATH, 'rb'))
img_byte_arr = BytesIO()
img.save(img_byte_arr, format=img.format)
img_byte_arr = img_byte_arr.getvalue()
client = boto3.client('runtime.sagemaker')
response = client.invoke_endpoint(EndpointName='ENDPOINT_NAME
Body=img_byte_arr,
ContentType='application/x-image')
response_body = response['Body']
print(response_body.read())

How can I retrieve the "Description" field of inspect.exe in my pywinauto based automation script?

I have the following SysTreeView32 element from which I would like to retrieve the "Description" field:
In my pywinauto script (based on win32 backend), I can retrieve pretty easily the TreeViewWrapper element by looking for the class type and eventually looking at the items text, but some information that I need is only available in the Description field of this element.
I was not able to find a way to retrieve this information.
I tried in UIA mode as well:
But in this case, it does not even appear in the information.
So I tried using the TreeItemWrapper element with the UIA backend in pywinauto, but I could not find the appropriate description not even in the UIAElementInfo. Although something looked pretty similar in the following line:
impl = uia_defs.get_elem_interface(elem, "LegacyIAccessible").
When I call the legacy_properties of the uia_controls.TreeItemWrapper, I get:
{'ChildId': 0,
'DefaultAction': '',
'Description': '',
'Help': '',
'KeyboardShortcut': '',
'Name': 'Execute multiple tasks(MultiTask_ImportSysD)',
'Role': 36,
'State': 3145730,
'Value': ''}
And in there, the Description is empty.
I'm guessing that property comes from IAccessible::get_accDescription.
MSDN says that property is deprecated but if you still want to use it, call AccessibleObjectFromWindow to get a IAccessible for a window.
Finally, I could not find this possibility through the pywinauto exposed API.
Although pywniauto does expose the Description property through the legacy_properties of the uia_controls.TreeItemWrapper instance, but it returns an empty string. This correlates with the note in teh Windows SDK documentation that states:
Note The Description property is often used incorrectly and is not supported by Microsoft UI Automation. Microsoft Active Accessibility server developers should not use this property. If more information is needed for accessibility and automation scenarios, use the properties supported by UI Automation elements and control patterns.
In the end, I finally developed a small piece of code to search for the element that I need the description of and I could retrieve the Description from there. Here is the code:
# for OleAcc access
import ctypes
import comtypes, comtypes.automation, comtypes.client
comtypes.client.GetModule('oleacc.dll')
def accDescription(iaccessible, cid):
objChildId = comtypes.automation.VARIANT()
objChildId.vt = comtypes.automation.VT_I4
objChildId.value = cid
objDescription = comtypes.automation.BSTR()
iaccessible._IAccessible__com__get_accDescription(objChildId, ctypes.byref(objDescription))
return objDescription.value
def accRole(iaccessible, cid):
objChildId = comtypes.automation.VARIANT()
objChildId.vt = comtypes.automation.VT_I4
objChildId.value = cid
objRole = comtypes.automation.VARIANT()
objRole.vt = comtypes.automation.VT_BSTR
iaccessible._IAccessible__com__get_accRole(objChildId, objRole)
return AccRoleNameMap[objRole.value]
def accState(iaccessible, cid):
'''Get Element State'''
objChildId = comtypes.automation.VARIANT()
objChildId.vt = comtypes.automation.VT_I4
objChildId.value = cid
objState = comtypes.automation.VARIANT()
iaccessible._IAccessible__com__get_accState(objChildId, ctypes.byref(objState))
return objState.value
def accName(iaccessible, cid):
'''Get Element Name'''
objChildId = comtypes.automation.VARIANT()
objChildId.vt = comtypes.automation.VT_I4
objChildId.value = cid
objName = comtypes.automation.BSTR()
iaccessible._IAccessible__com__get_accName(objChildId, ctypes.byref(objName))
return objName.value
def accDescendants(iaccessible):
"""Iterate all desencendants of an object iaccessible, including the current one.
Arguments:
iaccessible -- the IAccessible element to start from
Yields:
(IAcessible instance, Child id)
"""
yield (iaccessible, 0)
objAccChildArray = (comtypes.automation.VARIANT * iaccessible.accChildCount)()
objAccChildCount = ctypes.c_long()
ctypes.oledll.oleacc.AccessibleChildren(iaccessible, 0, iaccessible.accChildCount, objAccChildArray, ctypes.byref(objAccChildCount))
for i in range(objAccChildCount.value):
objAccChild = objAccChildArray[i]
if objAccChild.vt == comtypes.automation.VT_DISPATCH:
# query the sub element accessible interface
newiaccessible = objAccChild.value.QueryInterface(comtypes.gen.Accessibility.IAccessible)
# then loop over its descendants
for (__i, __c) in accDescendants(newiaccessible):
yield (__i, __c)
else: #if objAccChild.vt == comtypes.automation.VT_I4:
yield (iaccessible, objAccChild.value)
def findObjIAccessible(handle, text):
"""Find the IAccessible based on the name, starting from a specific window handle
Arguments:
handle -- the window handle from which to search for the element
text -- text that should be contained in the name of the IAccessible instance
Return:
(None, 0) if not found
(IAccessible instance, child id) of the first element whose name contains the text
"""
iacc = ctypes.POINTER(comtypes.gen.Accessibility.IAccessible)()
ctypes.oledll.oleacc.AccessibleObjectFromWindow(handle, 0, ctypes.byref(comtypes.gen.Accessibility.IAccessible._iid_), ctypes.byref(iacc))
for (ia, ch) in accDescendants(iacc):
n = accName(ia, ch)
if n != None and text in n:
return (ia, ch)
else:
return (None, 0)

Process facebook messenger url image

I'm trying to process this image provided by messenger-platform API (send-api-reference)
I used:
url = "https://scontent-lht6-1.xx.fbcdn.net/v/t34.0-12/20916840_10214193209010537_198030613_n.jpg?_nc_ad=z-m&oh=3eab9a3a400c7e05fb5b74c391852426&oe=5998B9A8"
#app.route('/photobot/<path:photo_url>')
def tensor_photobot(photo_url):
file = cStringIO.StringIO(urllib.urlopen(photo_url).read())
img = Image.open(file)
if img:
list_elements = process_image(img)
return json.dumps(list_elements)
But the image is not recognized. Any idea?
Message:
{u'mid': u'mid.$cAAbv-uhIfdVkIn9OVld8TqA6u2Hz', u'seq': 40125,
u'attachments': [{u'type': u'image', u'payload': {u'url':
u'https://scontent-lht6-1.xx.fbcdn.net/v/t34.0-12/20916840_10214193209010537_198030613_n.jpg?_nc_ad=z-m&oh=3eab9a3a400c7e05fb5b74c391852426&oe=5998B9A8'}}]}
[Reference][1] python 2.x
[1]:
https://developers.facebook.com/docs/messenger-platform/send-api-reference/image-attachment
Edit: following comment recommendations, I detected the problem is from url-string truncation.
I added all the implementation for more context.
From my comment in case the answer is needed by anyone in the future:
The query string is being truncated from the URL. To load the image, the entire URL including the query string is required.

Error in URL.getFile()

I am trying to open a file from URL.
Object of URL is created with getResource() method of ClassLoader.
Output URL returned from getResource() method is =
file:/C:/users/
After using URL.getFile() method which returns String as " /C:/users/ " it removes "file:" only not the "/ "
This / gives me a error in opening a file using new FileInputStream.
Error : FileNotFoundException
" / " in the starting of the filename causes the same problem in getting the path object.
Here , value of directory is retrieved from the URL.getResource().getFile()
Path Dest = Paths.get(Directory);
Error received is :
java.nio.file.InvalidPathException: Illegal char <:> at index 2: /C:/Users/
is anyone face such issue ?
Don't use URL.getFile(), it returns the "file" part of the URL, which is not the same as a file or path name of a file on disk. (It looks like it, but there are many ways in which there is a mismatch, as you have discovered.) Instead, call URL.toURI() and pass the resulting URI object to Paths.get()
That should work, as long as your URL points to a real file and not to a resource inside a jar file.
Example:
URL url = getClass().getResource("/some/resource/path");
Path dest = Paths.get(url.toURI());
The problem is that your result path contains leading /.
Try:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Path path = Paths.get(loader.getResource(filename).toURI());

Jython, ImageInfo

I trying to use ImageInfo and Jython to get information from a image on my harddrive.
I have imported the module fine but keep getting this error:
TypeError: setInput(): expected 2 args; got 1
And this is the code I am trying to use:
filename = "C:\\image.jpg"
img = ImageInfo.setInput(filename)
Could anyone point out what I am doing wrong.
Cheers
Eef
The missing argument Jython complains about is the ImageInfo object itself, which doesn't exist yet. You must construct it first. So:
filename = "C:\\image.jpg"
ii = ImageInfo()
img = ii.setInput(filename)
or
filename = "C:\\image.jpg"
img = ImageInfo().setInput(filename)
may work also.

Resources