How to pass an image to a function? - multithreading

Here is the code I used:
import threading
import cv2
def showimg(*a):
cv2.imshow('img', a)
cv2.waitKey(5)
cv2.destroyAllWindows()
def main():
img = cv2.imread('tree.jpg')
t = threading.Thread(target = showimg, args = (img) )
t.start()
if __name__ == '__main__':
main()
A simple code, how to pass a color image into a function?
I am getting an error like:
TypeError: mat is not a numerical tuple
I can't get my head around it.
Q1: What am I missing?
Q2: Does color and gray image work same?

I did not get why you were using import thread in the first place.
You can pass an image to a function relatively in a much easier way:
import cv2
def showimg(a):
cv2.imshow('img', a)
img = cv2.imread('tree.jpg')
showimg(img)
cv2.waitKey(0)

Related

Why wont this work? - def (function) not being called from main()

I need to be able to use classes, but trying to just get my simple code to work
import pandas as pd, numpy as np
class OutOfCountry7ViewModel():
def pandas_conversion(self):
#from csv import readers
deImport = pd.read_csv("ooc-exceptions.csv")
d1 = pd.read_csv("CS_Out_Of_Country.csv", encoding='windows-1252', parse_dates=True)
d2 = pd.read_csv("sccm-devices.csv", encoding='windows-1252')
d3 = pd.read_csv("CTLDAPRawData.csv", encoding='windows-1252')
#pandas join magic
lj_df1 = pd.merge(d1, d2, left_on="ComputerName", right_on="Name", how="left")
lj_df2 = pd.merge(d2, d3, left_on="PrimaryUser", right_on="Employee Number", how="left")
#lj_df = plj_df1d.join(lj_df2, lsuffix=)
df = (lj_df1)
#print(df)
df.to_csv('CS_Out_of_country_tabl.csv', index=False,header=df.columns, encoding='utf-8')
csv = 'CS_Out_of_country_tabl.csv'
return csv
def main():
pandas_conversion(self)
if __name__ == '__main__':
main()
i keep getting an error, NameError: name 'pandas_conversion' is not defined
Are you trying to do something like this? -
import pandas as pd, numpy as np
class OutOfCountry7ViewModel():
def pandas_conversion(self,csv):
...
def main(self):
self.pandas_conversion(csv)
if __name__ == '__main__':
some_object = OutOfCountry7ViewModel()
some_object.main()
This should work:
a = OutOfCountry7ViewModel()
a.pandas_conversion()
Hope this helped!
Try to remember the semantics and indentation of python.
Unused import numpy
Class/Parent Class has no (), Line 3
class OutOfCountry7ViewModel(): #wrong
class OutOfCountry7ViewModel: #right
There is no need of ()
df = (lj_df1)
#if you using some func then you miss that func name
If you're defining a method in the class you've to add instance self
def main(self):
pandas_conversion(self) #wrong calling func with parameter
I think your code is wrong because in PyCharm, it says def pandas_conversion(self): may be static.
So, your code is incomplete, there is something missing that we can't find.

Watermark in the photo

I'm making a watermark in the photo. How to make a watermark for several photos at once? and How to save multiple photos at once? which loop should be and in which part of the code?
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from PIL import ImageOps
def watermark_text(input_image_path,
output_image_path,
text, pos):
photo = Image.open(input_image_path)
drawing = ImageDraw.Draw(photo)
white = (3, 8, 12)
font = ImageFont.truetype("/Roboto-Regular.ttf", 150)
drawing.text(pos, text, fill=white, font=font)
photo.show()
photo.save(output_image_path)
if __name__ == '__main__':
img = 'new7093.JPG'
watermark_text(img, '11112.JPG',
text='sportves.ru',
pos=(300,500))
How about using multiprocessing.
from concurrent.futures import ProcessPoolExecutor
import os
img_list = os.listdir('path-to-image')
output_img_list = [i +'.output' for i in img_list]
text='sportves.ru'
pos=(300,500)
with ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(watermark_text, input_image_path, output_image_path, text, pos)
for input_image_path, output_image_path
in zip(img_list, output_img_list)
]
It is should work). Replace a save path and append images to put watermarks.
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
def watermark_text(input_image_path,
output_image_path,
text, pos):
global new_images
photo = Image.open(input_image_path)
drawing = ImageDraw.Draw(photo)
white = (3, 8, 12)
font = ImageFont.truetype("/Roboto-Regular.ttf", 150)
drawing.text(pos, text, fill=white, font=font)
photo.show()
new_images.append(photo)
if __name__ == '__main__':
images = ['new7093.JPG', 'something.phg'] # list of photos without watermark
new_images = [] # list of photos with watermark
for img in images:
watermark_text(img, '11112.JPG',
text='sportves.ru',
pos=(300, 500))
new_images[0].save(r'C:\Users\You\Desktop', save_all=True,
append_images=new_images[1:]) # replace by you path

'bool' object not iterable

I am working on python3, opencv 3.4 and using Microsoft Azure's FaceAPI function 'CF.face.detect()'
As far as I know, 'for loop' needs iterable object to run on like list but simple boolean is not iterable. Though 'res1' is a list I get this error.
TypeError: 'bool' object not iterable
Please help, Thanks in advance
Here is the code:
import unittest
import cognitive_face as CF
from PIL import Image, ImageFont, ImageDraw
import time
import cv2
from time import strftime
CF.Key.set('')
#print(CF.Key.get())
CF.BaseUrl.set('https://southeastasia.api.cognitive.microsoft.com/face/v1.0/')
#print(CF.BaseUrl.get())
"""Setup Person and Person Group related data."""
person_group_id = '' #id from training terminal
"""Unittest for `face.detect`."""
cap = cv2.VideoCapture('1.mp4')
while(cap.isOpened()):
ret, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print("\n\n ##########.... LOOKING FOR FACES ....########## \n\n")
res1 = []
print(type(res1))
res1 = CF.face.detect(cap)
print('\n This is the res1: ', res1)
c = len(res1)
print('\nTOTAL FACES FOUND:', c)
detect_id = [] ##error was here so put exception
for i in range(c):
print("\n\n ##########.... DETECTING FACES ....########## \n\n")
print('\n This is i in range c', i, c)
detect_id.append(res1[i]['faceId'])
#print('\n\n detected faces id ', detect_id[i])
width = res1[i]['faceRectangle']['width']
height = res1[i]['faceRectangle']['height']
x = res1[i]['faceRectangle']['left']
y = res1[i]['faceRectangle']['top']
################## IF ENDS #########################################################################
cv2.imshow('image',img)
k = cv2.waitKey(100) & 0xff
if k == 27:
break
################ WHILE ENDS ####################################
cap.release()
cv2.destroyAllWindows()
#Jonasz is right, you should be detecting faces on images, meaning, in frames from your mp4 file.
The method CF.face.detect expects an URI, so in the following code we'll write it to disk before pass it onto CF.face.detect:
cap = cv2.VideoCapture('1.mp4')
count = 0 # <--
while(cap.isOpened()):
ret, img = cap.read()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
filename = "frame%d.jpg" % count # <--
cv2.imwrite(filename, img) # <--
count+=1 # <--
print("\n\n ##########.... LOOKING FOR FACES ....########## \n\n")
res1 = []
print(type(res1))
res1 = CF.face.detect(filename) # <--
Shouldn't you use CF.face.detect on your captured image not on cap variable?

Drag and drop in QTreeView fails with items that hold a QImage

I have a list of items in a QTreeView. Each item holds a QImage object. If I try to drag and drop the item, the program freezes. But when I comment out the line objMod._Image = QImage(flags = Qt.AutoColor), the program runs fine.
How can I drag and drop the items with the QImage object? The QImage holds an image which is rendered. The rendering process takes a while, so it would be nice to keep the QImage object.
import sys
import os
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtUiTools import *
from PIL import Image, ImageCms, ImageQt
class ObjModel:
def __init__(self):
self._Image = None
class DragMoveTest(QMainWindow):
def __init__(self):
super(DragMoveTest,self).__init__()
self.initGUI()
self.show()
def initGUI(self):
self.treeView = QTreeView()
modelTreeView = QStandardItemModel()
self.treeView.setModel(modelTreeView)
for i in range(0, 4):
objMod = ObjModel()
objMod._Image = None
objMod._Image = QImage(flags = Qt.AutoColor)
item = QStandardItem('Test: %s' % str(i))
item.setData(objMod, Qt.UserRole + 1)
modelTreeView.invisibleRootItem().appendRow(item)
self.treeView.setDragDropMode(QAbstractItemView.InternalMove)
self.setCentralWidget(self.treeView)
def main(args):
app = QApplication(sys.argv)
qt_main_wnd = DragMoveTest()
ret = app.exec_()
sys.exit(ret)
if __name__ == "__main__":
main(sys.argv)
This is caused by a bug in PySide. During a drag and drop operation, the data in the dragged item must be serialized. This will be handled by Qt for most data-types, but for types that are specific to Python, special handling is required. This special handling seems to be broken in PySide. If your example is converted to PyQt, a TypeError is raised when trying to drag items, but the program does not freeze.
The source of the problem is that you are storing data using a custom Python class. PyQt uses pickle to serialize custom data-types, but it is not possible to also pickle the QImage that is stored in its __dict__, so the operation fails. I assume PySide must attempt something similar, but for some reason it does not raise an error when it fails. Qt grabs the mouse whilst dragging, so if the operation fails abnormally, it won't be released again, and the program will appear to freeze.
The simplest way to fix this is to avoid using a custom class to hold the QImage, and instead store the image directly in the item:
image = QImage()
item = QStandardItem('Test: %s' % i)
item.setData(image, Qt.UserRole + 1)
To store more data items, you can either use a different data-role for each one, or use a dict to hold them all:
data = {'image': QImage(), 'title': 'foo', 'timestamp': 1756790}
item.setData(data, Qt.UserRole + 1)
However, if you do this, you must always use string keys in the dict, otherwise you will face the same problems as before. (Using string keys means the dict can be converted into a QMap, which Qt knows how to serialize).
(NB: if you want to know whether a Qt class can be serialized, check the docs to see whether it defines the datastream operators).
I come up with a different solution. It is easier to have a object that holds a io.BytesIO. Your store the ImageData into the bytesIO variable. Upon on your image library you can open the image from the bytesIO variable.
In the demo the class ObjModel can handle QImage and Image from Pillow/PIL. If you use the set methods the image object will be converted into a bytesIO.
In short here a working example:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
import io
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtUiTools import *
from PIL import Image, ImageCms, ImageQt
########################################################################
class ObjModel:
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
self._ImageByteIO = None
#----------------------------------------------------------------------
def getObjByte(self):
""""""
return self._ImageByteIO
#----------------------------------------------------------------------
def getQImage(self):
""""""
try:
self._ImageByteIO.seek(0)
qImg = QImage.fromData(self._ImageByteIO.getvalue())
return qImg
except:
return None
#----------------------------------------------------------------------
def getPILImage(self):
""""""
try:
self._ImageByteIO.seek(0)
img = Image.open(tBytesIO)
return img
except:
return None
#----------------------------------------------------------------------
def setObjByte(self, fileName):
""""""
try:
tBytesIO = io.BytesIO()
f = open (fileName, 'rb')
tBytesIO.write(f.read())
f.close()
self._ImageByteIO = tBytesIO
except:
self._ImageByteIO = None
#----------------------------------------------------------------------
def setQImage(self, qImg):
""""""
try:
tBytesIO = io.BytesIO()
qByteArray = QByteArray()
qBuf = QBuffer(qByteArray)
qBuf.open(QIODevice.ReadWrite)
qImg.save(qBuf, 'PNG')
tBytesIO = io.BytesIO()
tBytesIO.write(qByteArray.data())
self._ImageByteIO = tBytesIO
except:
self._ImageByteIO = None
#----------------------------------------------------------------------
def setPILImage(self, pImg):
""""""
tBytesIO = io.BytesIO()
pImg.save(tBytesIO, 'png')
self._ImageByteIO = tBytesIO
#----------------------------------------------------------------------
class DragMoveTest(QMainWindow):
def __init__(self):
""""""
super(DragMoveTest,self).__init__()
self.initGUI()
self.show()
#----------------------------------------------------------------------
def initGUI(self):
""""""
self.treeView = QTreeView()
modelTreeView = QStandardItemModel()
self.treeView.setModel(modelTreeView)
for i in range(0, 4):
objMod = ObjModel()
objMod.setQImage(QImage(flags = Qt.AutoColor))
item = QStandardItem('Test: %s' % str(i))
item.setData(objMod, Qt.UserRole + 1)
modelTreeView.invisibleRootItem().appendRow(item)
self.treeView.setDragDropMode(QAbstractItemView.InternalMove)
self.setCentralWidget(self.treeView)
#----------------------------------------------------------------------
def main(args):
app = QApplication(sys.argv)
qt_main_wnd = DragMoveTest()
ret = app.exec_()
sys.exit(ret)
#----------------------------------------------------------------------
if __name__ == "__main__":
main(sys.argv)

How to speed up this code with Numpy?

Currently I am using the following code to convert all non-black pixels to white:
def convert(self, img):
for i in range(img.shape[0]):
for j in range(img.shape[1]):
if img.item(i, j) != 0:
img.itemset((i, j), 255)
return img
How can I speed it up?
All elements that are not 0 should change to 255:
a[a != 0] = 255
How about using PIL and make the function like this:
def convert (self,image):
return image.convert('1')
Test code:
from PIL import Image
import matplotlib.pyplot as plt
def convert (image):
return image.convert('1')
img = Image.open('./test.png')
plt.figure(); plt.imshow(img)
BW = convert(img)
plt.figure(); plt.imshow(BW)
plt.show()
result :
And btw, in case you needed the numpy array of the PIL image object, you can easily get it using:
matrix_of_img = numpy.asarray(img.convert('L'))

Resources