JGMS
Members-
Content Count
43 -
Joined
-
Last visited
Everything posted by JGMS
-
Tracking down exception in initialization section ? (RaiseExceptObject)
JGMS replied to Eric Grange's topic in RTL and Delphi Object Pascal
Hi @Eric, Did you manage to solve the issue altogether? I face the same problem in Delphi 11.3. At least: the same "call stack" listing appears as above in your initial post. In Win32 mode my FMX application (single unit, simple form, a menu and some speedbuttons) runs normally, but when switched to Win64 it fails. In ...source/rtl/system.pas the debug break is in: function _IsClass(const Child: TObject; Parent: TClass): Boolean; begin Result := (Child <> nil) and Child.InheritsFrom(Parent); end; The error is in "Parent". Thereafter the error "...c0000005 ACCES_VIOLATION..." appears. Any ideas how to solve this? -
Module "sentence_transformers" import in P4D not possible
JGMS replied to JGMS's topic in Python4Delphi
Thank you again @pyscripter, I just stared at Demo 33 code for quite a while. Indeed, it does not look trivial. It needs a deep dive. -
I found some nice Python code on WWW.SBERT.NET that perfectly suited my need to find the best matching images in two file sets. The file sets are related to each other: they origin the same celluloids, but were created with different quality of scanning equipment. In addition, cropping and tilting may have taken place, and in different ways. I modified the example code to create a file with information on the best fitting high-quality-version of the low-Q image, as well as the three top score values. Here is the code that runs perfectly in Python, version 3.10. I am using PyScripter: great! You can easily test it with your own files, though it may require a series of Python modules to be installed before it runs. from sentence_transformers import SentenceTransformer, util from PIL import Image model = SentenceTransformer("clip-ViT-B-32") f = open("E:/Fotos/testmap/ListMatchingFotos.txt", "a") lijst = ["E:/Fotos/File_nr1.JPG","E:/Fotos/File_nr2.JPG"] # this is the list of low quality images. image_names = ["M:/Fotos/negatieven 001.jpg","M:/Fotos/negatieven 002.jpg","M:/Fotos/negatieven 003.jpg","M:/Fotos/negatieven 004.jpg","M:/Fotos/negatieven 005.jpg","M:/Fotos/negatieven 006.jpg","M:/Fotos/negatieven 007.jpg","M:/Fotos/negatieven 008.jpg"] image_names += lijst encoded_image = model.encode([Image.open(filepath) for filepath in image_names], batch_size=128, convert_to_tensor=True, show_progress_bar=False) processed_images = util.paraphrase_mining_embeddings(encoded_image) threshold = 0.99 near_duplicates = [image for image in processed_images if image[0] < threshold] L = len(near_duplicates) for j in range(len(lijst)): # narrow the list of pairs to consider only the files in the "Lijst" searchresults = [] for i in range(0,L): score, image_id1, image_id2 = near_duplicates[i] idf = image_names.index(lijst[j]) if (( (image_names[image_id1] == image_names[idf] ) and (image_id2 != idf) ) and (not (image_names[image_id2] in lijst))) or (( (image_names[image_id2] == image_names[idf] ) and (image_id1 != idf) ) and (not (image_names[image_id1] in lijst))): searchresults.append( near_duplicates[i] ) ls = len(searchresults) score1 = 0 score2 = 0 score, image_id1, image_id2 = searchresults[0] if ls > 1: score1, image_id11, image_id21 = searchresults[1] if ls > 2: score2, image_id12, image_id22 = searchresults[2] if image_id1 != idf: image_id2 = image_id1 if score < 85/100: f.write( image_names[idf] + " " + image_names[image_id2] + " Score1: {:.3f}%".format(score * 100) + " Score2: {:.3f}%".format(score1 * 100) + " Score3: {:.3f}%".format(score2 * 100) + str(" NO MATCH OR VERY POOR \n")) else: f.write( image_names[idf] + " " + image_names[image_id2] + " Score1: {:.3f}%".format(score * 100) + " Score2: {:.3f}%".format(score1 * 100) + " Score3: {:.3f}%\n".format(score2 * 100)) f.close() However, the very same code doesn't run in Python4Delphi, although it uses the same PythonEngine.dll and path and libraries. I got the error message "Project .... raised exception class EPyAttributeError with message 'AttributeError: 'NoneType' object has no attribute 'flush'". The error is generated in the very first line "from sentence_transformers import...", on both modules, either combined or in separate lines. Here is my delphi version of the code above. Function TPyForm.Picture_Matching_using_Python(Foto_bestanden : String; VAR Zoeklijst :TArray<string>; TekstBestand :String; TargetScore : integer) : Boolean; VAR Mem :TStringList; Lijst, BeterLijst: String; Fotos : Tarray<String>; begin If Foto_bestanden = '' then exit; Fotos := Foto_bestanden.Split([',']); Lijst := '['; BeterLijst := '['; for Var Bestand : String in Fotos DO Lijst := Lijst + '"' + B2F(Bestand) + '"' + ','; Lijst := copy(Lijst,1,length(Lijst)-1)+ ']'; for Var Bestand : String in Zoeklijst DO BeterLijst := BeterLijst + '"' + B2F(Bestand) + '"' + ','; BeterLijst := copy(BeterLijst,1,length(BeterLijst)-1)+']'; TRY Mem := TStringList.Create; With Mem DO begin Add('import os'); Add('from PIL import Image'); Add(' from sentence_transformers import SentenceTransformer, util'); Add('model = SentenceTransformer("clip-ViT-B-32") '); Add('f = open("' + B2F(TekstBestand) + '", "a")'); Add('lijst = '+ Lijst ); Add('image_names = '+ BeterLijst ); Add('image_names += lijst'); Add('encoded_image = model.encode([Image.open(filepath) for filepath in image_names], batch_size=128, convert_to_tensor=True, show_progress_bar=False)'); Add('processed_images = util.paraphrase_mining_embeddings(encoded_image)'); Add('threshold = 99/100'); Add('near_duplicates = [image for image in processed_images if image[0] < threshold] '); Add('l = len(near_duplicates) '); Add('for j in range(len(lijst)): '); Add(' searchresults = [] '); Add(' for i in range(0,l): '); Add(' score, image_id1, image_id2 = near_duplicates[i] '); Add(' idf = image_names.index(lijst[j]) '); Add(' if (( (image_names[image_id1] == image_names[idf] ) and (image_id2 != idf) ) and (not (image_names[image_id2] in lijst))) or ' + ' (( (image_names[image_id2] == image_names[idf] ) and (image_id1 != idf) ) and (not (image_names[image_id1] in lijst))): '); Add(' searchresults.append( near_duplicates[i] ) '); Add(' ls = len(searchresults) '); Add(' score1 = 0' ); Add(' score2 = 0' ); Add(' score, image_id1, image_id2 = searchresults[0]'); Add(' if ls > 1: score1, image_id11, image_id21 = searchresults[1] '); Add(' if ls > 2: score2, image_id12, image_id22 = searchresults[2] '); Add(' if image_id1 != idf: image_id2 = image_id1'); Add(' if score < ' + TargetScore.tostring + '/100: '); Add(' f.write( image_names[idf] + " " + image_names[image_id2] + " Score1: {:.3f}%".format(score * 100) + " Score2: {:.3f}%".format(score1 * 100) + " Score3: {:.3f}%".format(score2 * 100) + str(" GEEN OF TWIJFELACHTIGE MATCH \n"))'); Add(' else:'); Add(' f.write( image_names[idf] + " " + image_names[image_id2] + " Score1: {:.3f}%".format(score * 100) + " Score2: {:.3f}%".format(score1 * 100) + " Score3: {:.3f}%\n".format(score2 * 100))' ); Add('f.close() '); end; TRY Result := True; PythonEngine1.ExecString( ansiString( Mem.text ) ); Except Result := False; END; FINALLY Mem.Free; END; end; I have no idea how to proceed, and do hope that anyone does. I would very much appreciate any help. Jan
-
Module "sentence_transformers" import in P4D not possible
JGMS replied to JGMS's topic in Python4Delphi
Thank you so much, @PyScripter. The error message indeed disappeared, and the code functioned like designed. However, the modifications envoked a new problem: it appears no longer possible to run the P4D routines in the background. If I try to do so, I got the error "...raised exception class $C0000005 with message 'c0000005 ACCESS_VIOLATION". Not only this occurs with the routine "Picture_Matching_using_Python" as shown above, but just with all of them if in background. I use the following calling code: TTask.Run( Procedure begin PyForm.Picture_Matching_using_Python(StringWithFilenames_CSV,MatchedList_Tarray, TextFileNameContainingMatchResults, some_info_Str, minimumscore_int ) ; TThread.Synchronize(nil, procedure begin ForceDirectories(NameCopyToFolder); for var j := 0 to length(MatchedList_Tarray) -1 do if MatchedList_Tarray[j] <> OriginalsList[j] then TFile.Copy(trim(MatchedList_Tarray[j]), NameCopyToFolder + trim(ExtractFileName(MatchedList_Tarray[j])), TRUE ) ; end); end); What can be the cause of this? I do hope you have suggestions on how to solve the issue. -
Module "sentence_transformers" import in P4D not possible
JGMS replied to JGMS's topic in Python4Delphi
I tried your suggestion, by adding "PythonEngine1.UseWindowsConsole:= True;" in the formcreate function, just before the LoadDLL command. The only effect was that a black command screen appeared for about half a second. The error message remained unchanged. -
Module "sentence_transformers" import in P4D not possible
JGMS replied to JGMS's topic in Python4Delphi
Thank you, and yes indeed. I am not sure whether I understand about "sys.version" and "sys.path". Where can I find these? I successfully use the following formcreate function in all my P4D projects, except for the line with "SetPythonHome", as I have added just now. The added line does not make any difference: the same error emerges. procedure TPyForm.FormCreate(Sender: TObject); begin MaskFPUExceptions(True); PythonEngine1 := TPythonEngine.Create(PyForm); PythonEngine1.RegVersion := '3.10'; PythonEngine1.DllName := 'python310.dll'; PythonEngine1.DllPath := 'C:\Users\myInlogName\AppData\Local\Programs\Python\Python310'; PythonEngine1.AutoLoad := false; PythonEngine1.AutoFinalize := true; PythonEngine1.AutoUnload := true; PythonEngine1.UseLastKnownVersion := false; PythonEngine1.RedirectIO := false; PythonDelphiVar1.Engine := PythonEngine1; PythonDelphiVar2.Engine := PythonEngine1; PythonDelphiVar3.Engine := PythonEngine1; PythonEngine1.SetPythonHome('C:\Users\myInlogName\AppData\Local\Programs\Python\Python310'); // I added this suggested code line here, in absence of a BeforeLoad event. PythonEngine1.loadDLL; PyEmbeddedResEnvironment3101.pythonEngine := PythonEngine1; PyEmbeddedResEnvironment3101.Autoload := True; end; -
After adding a new function that uses the "Numpy" and "CV2" libraries, lots of DLLs are loaded when the function is called. See "code" below. Initially, Delphi (or Python) complained because of missing the libraries. Then I copied the Numpy folder from the Python/3.10/site-packages of the machine to the ditto folders near the program. Apart from slowing down loading, the function fails, although it runs perfect in PyScripter. Is copying the folders Numpy and OpenCV sufficient? Or better: when compiling goes without complaining, could anything still be missing? Here are some of the messages, shown here in hope for that it rings a bell in anyone of you. If so, please let me know. Thanks ahead, jan Module Load: libffi-7.dll. No Debug Info. Base Address: $00007FF93C590000. Process FotoPower.exe (11132) Module Load: VCOMP140.DLL. No Debug Info. Base Address: $00007FF923BC0000. Process FotoPower.exe (11132) Module Load: MSVCP140.dll. No Debug Info. Base Address: $00007FF91FA50000. Process FotoPower.exe (11132) Module Load: _check_build.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF92F730000. Process FotoPower.exe (11132) onecore\com\combase\dcomrem\resolver.cxx(2414)\combase.dll!00007FF93FCA6FFA: (caller: 00007FF93FC0B9F8) ReturnHr(58) tid(2dc0) 80070005 Toegang geweigerd. Module Load: libopenblas64__v0.3.21-gcc_10_3_0.dll. Has Debug Info. Base Address: $00007FF8E9DA0000. Process FotoPower.exe (11132) Module Load: _multiarray_umath.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF8F19D0000. Process FotoPower.exe (11132) Module Load: _multiarray_tests.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF929EA0000. Process FotoPower.exe (11132) Module Load: _umath_linalg.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF923BA0000. Process FotoPower.exe (11132) Module Load: _pocketfft_internal.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF922860000. Process FotoPower.exe (11132) Module Load: mtrand.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF9197E0000. Process FotoPower.exe (11132) Module Load: bit_generator.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF921870000. Process FotoPower.exe (11132) Module Load: _common.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF9210D0000. Process FotoPower.exe (11132) Module Load: _hashlib.pyd. No Debug Info. Base Address: $00007FF9221F0000. Process FotoPower.exe (11132) Module Load: libcrypto-1_1.dll. No Debug Info. Base Address: $00007FF8F0440000. Process FotoPower.exe (11132) Module Load: _bounded_integers.cp310-win_amd64.pyd. No Debug Info. Base Address: $00007FF9201C0000. Process FotoPower.exe (11132)
-
Hi SwiftExpat, I created a folder with an embedded python 3.11 version in it, and installed all required libraries for my projects. Now my Delphi application(s) all have "PythonEngine1.DllPath" set to this "embedded folder". I installed the libraries from within with the "Scripts" subfolder using commands like ".\pip install opencv-contrib-python --no-warn-script-location". The command "python -m pip list -v" still returns the list of the libraries in the 3.10 system, though. Likely, that is due to the system's environment path setting, in where there is (and, I bet, should be) no entry added for the embedded version. I can live with that. Next, I compressed everthing in a zip file "Python.zip", with the intention to unpack this as "3.11" aside the executable on other machines, using Inno Setup. I can probably manage that, but after installation on the target machine the DLLPath should first be redirected to subfolder "3.11" in the path of the executable. On this one I am stuck. Do you have tips to achieve this path change? Or do you have helpful comments on the approach I described?
-
Thank you KoRiF, Being very unfamiliar with installing components, it took me quit some time to get things sorted out. I have the P4D sciences libs installed as components now. Next is getting them to work. I want OpenCV + Numpy to deal with image handling smoothly. Any tips for examples?
-
Thanks for your tip. I downloaded and unpacked it. I opened the file "P4DDataSciencesComponentSuite.groupproj" in Delphi and did "Build all Projects" of the group. This succeeded when for Windows- 32bit. Is there nothing more that I should do upfront to get all of these libraries available in P4D projects?
-
Both commands result in exactly the same list, though the contents of the folders are quite different. Can you explain how to install to an embedded list?
-
Programs with embedded P4D only run on my own PC, not on any other
JGMS posted a topic in Python4Delphi
My Delphi programs with the P4D-component PyEmbeddedResEnvironment310 run like a charm, as long as I keep them on my own machine (W11 + Delphi 11.3 Enterprise). On the target machines (W10), everything looks good: the embedded "3.10" environment is exactly the same, and contains all the required python libraries. Besides, I have the registry key "Computer\HKEY_CURRENT_USER\Software\Embarcadero\BDS\22.0\Environment Variables" adjusted through the batch file: "reg_env.bat", from P4D github. In there, "PYTHONENVIRONMENTDIR" reads "C:\Program Files\MyProgram", where the folder "3.10" stands aside the program executable (I also tried "C:\Program Files\MyProgram\3.10" by the way). Note that the programs work as normal, except for that the Python scripts don't work. No errors occur. Just no effects. What is it what I do wrong? Many thanks ahead. Jan -
Programs with embedded P4D only run on my own PC, not on any other
JGMS replied to JGMS's topic in Python4Delphi
@SwiftExpat After compiling, each of the "P4D-embedded" applications get their own python subfolder (like "3.10" in my case) within the directory of the executable. Considering disk space, using the same "PythonEngine1.DllPath" for all should be more efficient. How does this affect the installation of the program on other machines? I presume that the DLLPath should also be made available on the target machine, which may look a bit of weird. -
Programs with embedded P4D only run on my own PC, not on any other
JGMS replied to JGMS's topic in Python4Delphi
@KoRiFIndeed, that is exactly the case. Python and all required libraries come together with the executable in an associated folder "3.10". In my understanding this folder "3.10" (in my case) must be copied to the same directory as of the Delphi executable in the target machine, although "PyEmbedded" hints me to having it all inside the executable. Might still be possible, I hope. Anyway, there is no need to install Python on the target machine. Moreover, it works like a charm! -
Programs with embedded P4D only run on my own PC, not on any other
JGMS replied to JGMS's topic in Python4Delphi
@SwiftExpatThat was the perfect answer! Thank you very much, indeed. Before starting the program I removed the Environment path referencing the installed Python version. I was happy to see that the program runs independently. Just like I want it. I added "PythonEngine1.DllPath := IncludeTrailingPathDelimiter(ExtractFileDir(Application.ExeName)) + PythonEngine1.RegVersion;" to the code. Great. -
Programs with embedded P4D only run on my own PC, not on any other
JGMS replied to JGMS's topic in Python4Delphi
Thanks for your reply @KoRif, I found out that my (VCL) programs use the installed version on the target machine, rather than the embedded version of Python in the program. The debug-version of the executable showed errors that libraries were missing. These libraries were included in the side-packages subfolder associated with the executable, but were absent in the Python folder of the machine. Apparently, there is no embedding! Thus the question remains: what do I wrong? I use the following code for the creation of the Python form: procedure TPyForm.FormCreate(Sender: TObject); begin MaskFPUExceptions(True); PythonEngine1 := TPythonEngine.Create(PyForm); PythonEngine1.RegVersion := '3.10'; PythonEngine1.DllName := 'python310.dll'; PythonEngine1.AutoLoad := false; PythonEngine1.AutoFinalize := true; PythonEngine1.AutoUnload := true; PythonEngine1.UseLastKnownVersion := false; PythonEngine1.RedirectIO := false; PythonEngine1.loadDLL; PyEmbeddedResEnvironment3101.pythonEngine := PythonEngine1; PyEmbeddedResEnvironment3101.Autoload := True; end; When the project is compiled the folder 3.10 is created or updated, with all required libraries in it. An installation program copies everything that is needed to the target machine. So far so good, I'd presume. What more is needed? Anything specific in the registry settings, like "Environment Variables"? -
P4D is great! I use it with pleasure, backboned by PyScripter, great as well!) to test my code beforehand. The following Python code works perfect in PyScripter, but not in P4D in Delphi 11.2 or 11.3 import cv2 import imutils image = cv2.imread("E:/APPS/ScannedFotos/DCIM/100MEDIA/PICT0022.JPG") image_rotated = imutils.rotate(image, 2) cv2.imwrite("E:/APPS/ScannedFotos/DCIM/100MEDIA/PICT0022.JPG", image_rotated, [int(cv2.IMWRITE_JPEG_QUALITY), 80]) In Delphi (VCL) I have have a form with a TPyEmbeddedResEnvironment310. All required Python libraries are present in de 3.10 folder within the Win64 subfolder of the Delphi code. (numpy, cv2, imutils, etc...) The PythonEngine is loaded in the formcreation routine like so: procedure TPyForm.FormCreate(Sender: TObject); begin PythonEngine1 := TPythonEngine.Create(PyForm); PythonEngine1.RegVersion := '3.10'; PythonEngine1.DllName := 'python310.dll'; PythonEngine1.AutoLoad := false; PythonEngine1.AutoFinalize := true; PythonEngine1.AutoUnload := true; PythonEngine1.UseLastKnownVersion := false; PythonEngine1.RedirectIO := false; PythonEngine1.loadDLL; PyEmbeddedResEnvironment3101.pythonEngine := PythonEngine1; PyEmbeddedResEnvironment3101.Autoload := True; end; The function that should work (like many others I have created so far): Function TPyForm.Rotate_Plaatje_Met_CV2(Foto_bestand : String; Hoek : Double) : Boolean; VAR Mem :TStringList; begin Foto_bestand := B2F(Foto_bestand) ; TRY Mem := TStringList.Create; if FileExists(Foto_Bestand) then With Mem DO begin Add( 'import cv2 ' ); Add( 'import imutils' ); Add( 'image = cv2.imread("' + Foto_bestand + '")'); Add( 'i = ' + Hoek.ToString ); Add( 'image_rotated = imutils.rotate(image, i) ' ); Add( 'cv2.imwrite("'+ Foto_bestand + '", image_rotated, [int(cv2.IMWRITE_JPEG_QUALITY), 80]) '); end; TRY PythonEngine1.ExecString( ansiString( Mem.text ) ); Result := True; Except Result := False; END; FINALLY Mem.Free; END; end; I have no idea what is wrong. I tried lots of different ways with CV2 codes found on the internet, but all without success. I keep ketting the messages: Project ....exe raised exception class $C000008E with message 'c000008e FLOAT_DIVIDE_BY_ZERO'. and when trying once more directly therafter: Project ....exe raised exception class EPyAttributeError with message 'AttributeError: partially initialized module 'cv2' has no attribute 'INTER_AREA' (most likely due to a circular import)'. I hope anybody can help me out of this circle. Because it just runs in PyScripter, it must be solvable, isn't it? Many thanks ahead. Jan
-
Thank you so much! I am so sorry that I did not recently look at this forum! It works now! Unbelievable. P4D is even greater now! Regards, Jan