Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
can't find libpHash
#1
Dear community,

I want to use the 3 pHash functions (ph_dct_imagehash, ph_image_digest and ph_mh_imagehash) to compare which fits best for me...

I tried it many hours (install problems..., searching the web...) but now I can't go any further...

I can call the 2 functions ph_image_digest and ph_dct_imagehash, ph_mh_imagehash is not available.

But when I run the script, it is mentioned:

Error:
Traceback (most recent call last): File "D:\programmierOrdner\python-Programmierung\hangerfinder\main.py", line 7, in <module> from phash import ph_image_digest File "C:\Users\AppData\Local\Programs\Python\Python311\Lib\site-packages\phash\__init__.py", line 4, in <module> from .phash_ctypes import * File "C:\Users\AppData\Local\Programs\Python\Python311\Lib\site-packages\phash\phash_ctypes.py", line 17, in <module> raise ImportError('Cannot find libpHash!') ImportError: Cannot find libpHash!
I tried very long to install libpHash - witout any success...

How can I fix the importError "ImportError: Cannot find libpHash!"?

Could you please help me out?

import os
import time
import ctypes
from multiprocessing import Pool

from PIL import Image
from phash import ph_image_digest
from phash import ph_dct_imagehash
from phash import ph_crosscorr

p = "D:/S8_hanger_finder/neuer_Ansatz/phash_test/"


def create_phash(frame):
    # load frames
    frame = Image.open(p + str(frame))
    # create pHash
    # Compare hashes to determine whether the frames are the same or not
    phash = str(ph_image_digest(frame))
    return phash


# def difference_count(a: str, b: str) -> int:
#     # count differences between a and b
#     return sum(1 for a, b in zip_longest(a, b) if a != b)
def difference_count(a: str, b: str) -> int:
    # count differences between a and b
    return ph_crosscorr(a, b)


def phash_iter(d):
    # frame phash iterator
    # use multiprocessing to hash frames in parallel
    pool = Pool(processes=6)
    for index, phash in enumerate(pool.imap(create_phash, d, chunksize=1)):
        yield index, phash


def detect_hangers(phash_iter, threshold: int = 0, min_count: int = 4):
    """Return list of "hangers" detected in frame_hash_list.
    A "hanger" is consecutive frames that are the same.

    frame_hash_list : list of frame hash strings.  Frames are considered
    same or different by counting the differences in their hash strings.

    threshold : Maximum number of diffences allowed for two frames to be
    considered "same".

    min_count : Minimum length of a hanger.  Short hangers aren't noticable
    and don't have to be removed.
    """
    hangers = []  # List of hanger start, stop frame indexes
    start_index, start_phash = next(phash_iter)
    for index, phash in phash_iter:
        print(index, phash)
        # Are frame and start_frame disimilar enough?
        if difference_count(start_phash, phash) > threshold:
            if index - start_index >= min_count:
                # Add hanger to list
                hangers.append((start_index, index - 1))
            start_phash = phash
            start_index = index
    # Check if we end with a hanger
    if index - start_index > 10:
        hangers.append([start_index, index])
    return hangers


if __name__ == "__main__":
    begin = time.time()
    all_frames = os.listdir(p)
    hangers = detect_hangers(phash_iter(all_frames))
    end = time.time()

    print('hangers:')
    print(hangers)
    numberOfHangers = len(hangers)
    print('number of hangers: ' + str(numberOfHangers))
    print('time: ' + str(end - begin))
Reply
#2
Did you go to the package homepage?

https://github.com/JohannesBuchner/imagehash

Quote:Installation
Based on PIL/Pillow Image, numpy and scipy.fftpack (for pHash) Easy installation through pypi:

Do you have numpy and scipy.fftpack installed?
Reply
#3
Hi,

I did everything but the error remains...

Greetings,

flash77
Reply
#4
Photo 
Dear community,

I would like to test the 3 hash functions (ph_dct_imagehash, ph_image_digest and ph_mh_imagehash) to know which one works well for my needs.

I tried it many hours but now I can't go any further...

How can I fix the importError "ImportError: Cannot find libpHash!"?

I would be very happy about hints, because I don't know exactly why the package is not found.

I'm using Pycharm and a virtual enviroment.

I hereby attach the error messages that appear in Pycharm - please have a look.

Thanks for your help...

Have a nice weekend...

Attached Files

Thumbnail(s)
               
Reply
#5
Please post errors as text, not screenshots. I cannot cut/paste text from a screenshot.
Reply
#6
Should find a alternative to python-phash it's old and documentation dos not work.
Most run Makefile with a C/C++ complier and link to libpHash,none of this is documented or for sure never tested on Windows.
Code has been unmaintained for 8-years.
Reply
#7
Hello deanhystad, hello snippsat, thanks for your replies. Unfortunately I wasn't able to look into the forum earlier. I'll paste the error messages as text tomorrow when I get back to work.
I wish a nice evening...
Reply
#8
Don't waste your time posting error message. I wrote my reply thinking you were using a different phash package. snippsat provided the correct answer to your problem; use a package that is up-to-date and maintained.
Reply
#9
Dear community,

with the great support of this forum I made a perceptual-hash-hanger-finder for digitized super8-films.

Thanks a lot for helping me so much...

As a final step, I'm trying to get a PyQt6 dialog. I have the following problem:

In line 159 I created a function:
def button_HF_Start_click():

If I click on the button of the dialog, then the hangerfinder is executed.
But when I close the dialog, the hangerfinder is run again. At the moment I'm stuck...

Maybe someone can give me a hint...
Thanks very much!!

from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QVBoxLayout
import os
import time
import openpyxl
from itertools import zip_longest
from multiprocessing import Pool
from PIL import Image
import imagehash

p = "C:/hangerfinder/bild_analyse/"

def create_phash(frame):
    # load frames
    frame = Image.open(p + str(frame))
    # create pHash
    # Compare hashes to determine whether the frames are the same or not
    phash = str(imagehash.phash(frame))
    return phash


def difference_count(a: str, b: str) -> int:
    # count differences between a and b
    return sum(1 for a, b in zip_longest(a, b) if a != b)


def phash_iter(d):
    # frame phash iterator
    # use multiprocessing to hash frames in parallel
    pool = Pool(processes=6)
    for index, phash in enumerate(pool.imap(create_phash, d, chunksize=1)):
        yield index, phash


def detect_hangers(phash_iter, threshold: int = 0, min_count: int = 5):
    """Return list of "hangers" detected in frame_hash_list.
    A "hanger" is consecutive frames that are the same.

    frame_hash_list : list of frame hash strings.  Frames are considered
    same or different by counting the differences in their hash strings.

    threshold : Maximum number of diffences allowed for two frames to be
    considered "same".

    min_count : Minimum length of a hanger.  Short hangers aren't noticable
    and don't have to be removed.
    """
    hangers = []  # List of hanger start, stop frame indexes
    start_index, start_phash = next(phash_iter)
    for index, phash in phash_iter:
        print(index, phash)
        # Are frame and start_frame disimilar enough?
        if abs(difference_count(start_phash, phash)) > threshold:
            if index - start_index >= min_count:
                # Add hanger to list
                hangers.append((start_index, index - 1))
            start_phash = phash
            start_index = index
    # Check if we end with a hanger
    if index - start_index > 10:
        hangers.append([start_index, index])
    return hangers

def convert_frame_nr_in_time(d):
    # S8-Movie (avi-file) is checked of hangers
    #####################################################
    # 1 hour contains 72000 frames
    c1 = 72000
    # 1 minute contains 1200 frames
    c2 = 1200
    # 1 second contains 20 frames
    c3 = 20

    def find_even_frame_nr(a, b, c):
        while True:
            if a % c == 0:
                break
            else:
                a -= 1
                b += 1
        return a, b

    frame_nr_full_hour, rest_1 = find_even_frame_nr(d, 0, c1)
    number_of_hours = frame_nr_full_hour / c1
    ###########################################################
    frame_nr_full_minute, rest_2 = find_even_frame_nr(rest_1, 0, c2)
    number_of_minutes = frame_nr_full_minute / c2
    ###########################################################
    frame_nr_full_second, rest_3 = find_even_frame_nr(rest_2, 0, c3)
    number_of_seconds = frame_nr_full_second / c3

    return number_of_hours, number_of_minutes, number_of_seconds


def fill_hanger_information_in_excel(hangers):
    pH = "C:\hangerfinder\S8-Hanger_Positionen.xlsm"
    fileXLSX = openpyxl.load_workbook(pH, keep_vba=True)
    sheet = fileXLSX["Blatt"]

    # find film to check for hangers in excel
    # film was marked with "x" by me
    r = 2
    for c in range(2, 82, 4):
        if sheet.cell(r, c).value == "x":
            hanger_start_col = c
            hanger_end_col = c + 2

    # clear old hanger information
    # film doesn't have more than 100 hangers
    clear_row = 5
    clear_col = hanger_start_col
    for z in range(clear_row, clear_row + 100):
        for s in range(clear_col, clear_col + 3):
            sheet.cell(row=z, column=s).value = None

    # fill in hanger information
    r = 5
    for i in hangers:
        frame_nr_hanger_start = i[0]
        frame_nr_hanger_end = i[1]
        number_of_hours_start, number_of_minutes_start, number_of_seconds_start = convert_frame_nr_in_time(
            frame_nr_hanger_start)
        number_of_hours_end, number_of_minutes_end, number_of_seconds_end = convert_frame_nr_in_time(
            frame_nr_hanger_end)
        number_of_hours_start_int = int(number_of_hours_start)
        number_of_minutes_start_int = int(number_of_minutes_start)
        number_of_seconds_start_int = int(number_of_seconds_start)
        number_of_hours_end_int = int(number_of_hours_end)
        number_of_minutes_end_int = int(number_of_minutes_end)
        number_of_seconds_end_int = int(number_of_seconds_end)

        number_of_hours_start_str = str(number_of_hours_start_int)
        if len(number_of_hours_start_str) == 1:
            number_of_hours_start_str = "0" + number_of_hours_start_str
        number_of_minutes_start_str = str(number_of_minutes_start_int)
        if len(number_of_minutes_start_str) == 1:
            number_of_minutes_start_str = "0" + number_of_minutes_start_str
        number_of_seconds_start_str = str(number_of_seconds_start_int)
        if len(number_of_seconds_start_str) == 1:
            number_of_seconds_start_str = "0" + number_of_seconds_start_str
        number_of_hours_end_str = str(number_of_hours_end_int)
        if len(number_of_hours_end_str) == 1:
            number_of_hours_end_str = "0" + number_of_hours_end_str
        number_of_minutes_end_str = str(number_of_minutes_end_int)
        if len(number_of_minutes_end_str) == 1:
            number_of_minutes_end_str = "0" + number_of_minutes_end_str
        number_of_seconds_end_str = str(number_of_seconds_end_int)
        if len(number_of_seconds_end_str) == 1:
            number_of_seconds_end_str = "0" + number_of_seconds_end_str

        # create timestamp
        timestamp_start_str = number_of_hours_start_str + ":" + number_of_minutes_start_str + ":" + number_of_seconds_start_str
        timestamp_end_str = number_of_hours_end_str + ":" + number_of_minutes_end_str + ":" + number_of_seconds_end_str
        sheet.cell(row=r, column=hanger_start_col).value = timestamp_start_str
        sheet.cell(row=r, column=hanger_end_col).value = timestamp_end_str
        r += 1
    fileXLSX.save(pH)
    fileXLSX.close

def button_HF_Start_click():
    begin = time.time()
    all_frames = os.listdir(p)
    hangers = detect_hangers(phash_iter(all_frames))
    end = time.time()
    print('hangers:')
    print(hangers)
    numberOfHangers = len(hangers)
    print('number of hangers: ' + str(numberOfHangers))
    print('time: ' + str(end - begin))
    return hangers

if __name__ == "__main__":
    app = QApplication([])
    window = QWidget()
    layout = QVBoxLayout()
    button_HF_Start = QPushButton("Hängerfinder ausführen")
    layout.addWidget(button_HF_Start)
    window.setLayout(layout)
    button_HF_Start.clicked.connect(button_HF_Start_click)
    window.show()
    app.exec()
    hangers = button_HF_Start_click()
    fill_hanger_information_in_excel(hangers)
Reply
#10
Hi,

this works:

def button_HF_Start_click():
    begin = time.time()
    all_frames = os.listdir(p)
    threshold = textboxT.text()
    min_count = textboxM.text()
    hangers = detect_hangers(phash_iter(all_frames), int(threshold), int(min_count))
    fill_hanger_information_in_excel(hangers)
    end = time.time()
    print('hangers:')
    print(hangers)
    numberOfHangers = len(hangers)
    print('number of hangers: ' + str(numberOfHangers))
    print('time: ' + str(end - begin))
    return hangers

if __name__ == "__main__":
    app = QApplication([sys.argv])
    window = QWidget()
    button_HF_Start = QPushButton("Hängerfinder ausführen")
    textboxT = QLineEdit()
    textboxM = QLineEdit()
    layout = QVBoxLayout()
    layout.addWidget(button_HF_Start)
    layout.addWidget(textboxT)
    layout.addWidget(textboxM)
    window.setLayout(layout)
    window.show()
    button_HF_Start.clicked.connect(button_HF_Start_click)
    sys.exit(app.exec())
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020