B4J Question 1st PyBridge try: alfa-test

peacemaker

Expert
Licensed User
Longtime User
Hi, All and @Erel ,

Just tried for the first time your PyBridge draft. B4J 10.0
Compiling at line:
Dim correctClassesNames As Map = jo.InitializeStatic("anywheresoftware.b4a.randomaccessfile.RandomAccessFile").GetField("correctedClasses")
gives the error:
Waiting for debugger to connect...
Program started.
Error occurred on line: 18 (PyComm)
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at anywheresoftware.b4a.keywords.Common.CallSubDebug2(Common.java:486)
at b4j.example.b4xpagesmanager._createpageifneeded(b4xpagesmanager.java:875)
at b4j.example.b4xpagesmanager._showpage(b4xpagesmanager.java:354)
at b4j.example.b4xpagesmanager._addpage(b4xpagesmanager.java:175)
at b4j.example.b4xpagesmanager._addpageandcreate(b4xpagesmanager.java:189)
at b4j.example.b4xpagesmanager._initialize(b4xpagesmanager.java:125)
at b4j.example.main._appstart(main.java:85)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:237)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at b4j.example.main.start(main.java:38)
at [email protected]/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at [email protected]/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
at [email protected]/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at [email protected]/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at [email protected]/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:134)
at anywheresoftware.b4a.debug.Debug.CallSubNew2(Debug.java:81)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
... 28 more
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:115)
... 30 more
Caused by: java.lang.RuntimeException: Field: correctedClasses not found in: anywheresoftware.b4a.randomaccessfile.RandomAccessFile
at anywheresoftware.b4j.object.JavaObject$FieldCache.getField(JavaObject.java:307)
at anywheresoftware.b4j.object.JavaObject.GetField(JavaObject.java:182)
at b4j.example.pycomm._initialize(pycomm.java:108)
at b4j.example.pybridge._start(pybridge.java:181)
at b4j.example.b4xmainpage$ResumableSub_B4XPage_Created.resume(b4xmainpage.java:130)
at b4j.example.b4xmainpage._b4xpage_created(b4xmainpage.java:84)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
... 32 more
Just alfa-test...
Any updates in jRandomAccessFile lib?
 

Attachments

  • TempDownload.png
    TempDownload.png
    17.8 KB · Views: 149
Last edited:

Daestrum

Expert
Licensed User
Longtime User
Ok can be... recognition counting persons
it would be something similar to this (not tried as I dont have hundreds of images to train it)

B4X:
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
import numpy as np
from keras.utils import Sequence
from keras.preprocessing.image import load_img, img_to_array

class DataGenerator(Sequence):
    def __init__(self, image_filenames, labels, batch_size, img_size):
        self.image_filenames = image_filenames
        self.labels = labels
        self.batch_size = batch_size
        self.img_size = img_size
    def __len__(self):
        return int(np.ceil(len(self.image_filenames) / self.batch_size))
    def __getitem__(self, idx):
        batch_x = self.image_filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]
        images = [img_to_array(load_img(file_name, target_size=self.img_size)) for file_name in batch_x]
        return np.array(images), np.array(batch_y)

# Load dataset
import pandas as pd
def read_training_data(path_to_labels_csv):
    global model
    data = pd.read_csv(path_to_labels_csv)
    image_filenames = data['filename'].values
    labels = data['count'].values
    # Create data generator   batch size < number of pics
    train_gen = DataGenerator(image_filenames, labels, batch_size=32, img_size=(128, 128))
    # Train the model
    model.fit(train_gen, epochs=10, validation_data=validation_gen)
    return f"Finished Training""

# Function to preprocess and predict the count of people in a new image
def predict_people_count(model, image_path):
    # Load and preprocess the image
    image = load_img(image_path, target_size=(128, 128))
    image_array = img_to_array(image)
    image_array = np.expand_dims(image_array, axis=0)  # Add batch dimension
    image_array = preprocess_input(image_array)
    # Make prediction
    prediction = model.predict(image_array)
    count = int(np.round(prediction[0][0]))  # Round and convert to integer
    return count

# Example usage
def count_people(image_path):
    people_count = predict_people_count(model, image_path)
    return f'I see {people_count} people in the image.'

you would have a csv (where count is the number of people in the image and filemane is the image url)

filename,count
c:\xxx\img1.png,0
c:\xxx\img2.png,0
...
c:\xxx\img100.png,1
...
c:\xxx\img200.png,2

and call from B4J like
B4X:
    Wait for (Py.Utils.RunCode("read_training_data",array("path-to-csv"), Code).Fetch) Complete(Result As PyWrapper)
    Log(Result.Value.As(String))
...
    Wait for (Py.Utils.RunCode("count_people",array("path-to-new-image"), Code).Fetch) Complete(Result As PyWrapper)
    Log(Result.Value.As(String))

You would have exxtra code to save/load the model so you could just use for new images after training it.
 
Last edited:
Upvote 0

Magma

Expert
Licensed User
Longtime User
it would be something similar to this (not tried as I dont have hundreds of images to train it)

B4X:
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
import numpy as np
from keras.utils import Sequence
from keras.preprocessing.image import load_img, img_to_array

class DataGenerator(Sequence):
    def __init__(self, image_filenames, labels, batch_size, img_size):
        self.image_filenames = image_filenames
        self.labels = labels
        self.batch_size = batch_size
        self.img_size = img_size
    def __len__(self):
        return int(np.ceil(len(self.image_filenames) / self.batch_size))
    def __getitem__(self, idx):
        batch_x = self.image_filenames[idx * self.batch_size:(idx + 1) * self.batch_size]
        batch_y = self.labels[idx * self.batch_size:(idx + 1) * self.batch_size]
        images = [img_to_array(load_img(file_name, target_size=self.img_size)) for file_name in batch_x]
        return np.array(images), np.array(batch_y)

# Load dataset
import pandas as pd
def read_training_data(path_to_labels_csv):
    global model
    data = pd.read_csv(path_to_labels_csv)
    image_filenames = data['filename'].values
    labels = data['count'].values
    # Create data generator   batch size < number of pics
    train_gen = DataGenerator(image_filenames, labels, batch_size=32, img_size=(128, 128))
    # Train the model
    model.fit(train_gen, epochs=10, validation_data=validation_gen)
    return f"Finished Training""

# Function to preprocess and predict the count of people in a new image
def predict_people_count(model, image_path):
    # Load and preprocess the image
    image = load_img(image_path, target_size=(128, 128))
    image_array = img_to_array(image)
    image_array = np.expand_dims(image_array, axis=0)  # Add batch dimension
    image_array = preprocess_input(image_array)
    # Make prediction
    prediction = model.predict(image_array)
    count = int(np.round(prediction[0][0]))  # Round and convert to integer
    return count

# Example usage
def count_people(image_path):
    people_count = predict_people_count(model, image_path)
    return f'I see {people_count} people in the image.'

you would have a csv (where count is the number of people in the image and filemane is the image url)

filename,count
c:\xxx\img1.png,0
c:\xxx\img2.png,0
...
c:\xxx\img100.png,1
...
c:\xxx\img200.png,2

and call from B4J like
B4X:
    Wait for (Py.Utils.RunCode("read_training_data",array("path-to-csv"), Code).Fetch) Complete(Result As PyWrapper)
    Log(Result.Value.As(String))
...
    Wait for (Py.Utils.RunCode("count_people",array("path-to-new-image"), Code).Fetch) Complete(Result As PyWrapper)
    Log(Result.Value.As(String))

You would have exxtra code to save/load the model so you could just use for new images after training it.
Wow, in this example... the images will have zero people at first and then at same scene of image (3-100) different people and changing their number +1 every time... ??

also... this command: "target_size=(128, 128)"
What means ? are pixels... array ?
 
Last edited:
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
yes series of pics with 0,1,2,3...people does not have to be same scene, only the number of people.

target_size is the image size the software works on, will resize images on load,
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
yes, you can change it to a larger size, but the training time will increase (128 x 128 > 512 x 512 at least 16 times longer to train). (Big commercial models take millions of GPU hours to train, and they dont use consumere GPU either)
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Another good lib is pandas
Example
csv file like this (needs the header line to work by names)
B4X:
name,age,gender
fred,24,male
julie,20,female
mike,44,male
susan,55,female

Python Code
B4X:
import pandas as pd
def to_a_list(col_name,filename,query):

    # Load CSV file into a DataFrame
    df = pd.read_csv(filename)
    # select data on contents of query
    screened_data = df.query(query)

    # Get the data in the 'column_name' column as a list
    column_data = screened_data[col_name].values.tolist()

    # return the list
    return column_data

B4J code (ignoring setup of PyBridge)
B4X:
Private Sub Button1_Click
' the query is "age> 30  & gender=='female'"
    wait for (csvToList(File.DirAssets,"testfile.csv","age>30 & gender=='female'")) Complete (rr As List)
    'print out the list of csv records founds
    For Each n As String In rr
        Log(n) 
    Next
End Sub

Sub csvToList(path As String,fname As String, criteria As String)As ResumableSub
    Dim cols As List = Array("name","gender","age")  ' these are the columns I want in this order, query cols dont have to be in it
' execute the python script from DirAssets called csv.py
    Wait for (Py.Utils.RunCode("to_a_list", Array(cols, File.GetUri(path,fname), criteria), File.ReadString(path,"csv.py")).Fetch) Complete(Result As PyWrapper)
' return the list
    Return Result.Value.As(List)
End Sub
 
Upvote 0
Top