अजगर से छवियों को निकालने के बिना, अजगर में निकालें?


81

एक पीडीएफ दस्तावेज़ से सभी छवियों को कैसे निकाला जा सकता है, मूल संकल्प और प्रारूप में? (मतलब टिफ़ के रूप में एक्सफोलिएशन, जेपीईजी के रूप में जेपीआर, आदि और फिर से रेज़म्पलिंग के बिना)। लेआउट महत्वहीन है, मुझे परवाह नहीं है कि स्रोत छवि पृष्ठ पर स्थित है।

मैं अजगर 2.7 का उपयोग कर रहा हूं, लेकिन आवश्यकता पड़ने पर 3.x का उपयोग कर सकता हूं।


धन्यवाद। वह "PDF में छवियाँ कैसे संग्रहीत की जाती हैं" url ने काम नहीं किया, लेकिन ऐसा लगता है: jpedal.org/PDFblog/2010/04/…
nealmcb

एक जेपीडाल जावा लाइब्रेरी है, जो पीडीएफ क्लिप्ड इमेज एक्सट्रैक्शन कहलाती है । लेखक, मार्क स्टीफेंस का एक संक्षिप्त हाइलेवल ओवरव्यू है कि कैसे छवियों को पीडीएफ में संग्रहीत किया जाता है जो किसी अजगर निकालने वाले को बनाने में मदद कर सकता है।
मैट विल्की

जवाबों:


47

आप मॉड्यूल PyMuPDF का उपयोग कर सकते हैं। यह सभी छवियों को .png फ़ाइलों के रूप में आउटपुट करता है, लेकिन बॉक्स से बाहर काम करता है और तेज होता है।

import fitz
doc = fitz.open("file.pdf")
for i in range(len(doc)):
    for img in doc.getPageImageList(i):
        xref = img[0]
        pix = fitz.Pixmap(doc, xref)
        if pix.n < 5:       # this is GRAY or RGB
            pix.writePNG("p%s-%s.png" % (i, xref))
        else:               # CMYK: convert to RGB first
            pix1 = fitz.Pixmap(fitz.csRGB, pix)
            pix1.writePNG("p%s-%s.png" % (i, xref))
            pix1 = None
        pix = None

अधिक संसाधनों के लिए यहां देखें


2
यह महान काम करता है! ( pip install pymudfपहले स्पष्ट रूप से आवश्यक)
बसज

9
* pip install pymupdfसाथी गुगुलर्स के लिए जो सोच रहे हैं कि उपरोक्त स्थापना विफल क्यों होती है
वीएसजेडएम

9
अधिक जानकारी की pip install pymupdfकोशिश करने के बजायpip install PyMuPDF
दमोटेरी

1
इस कोड से मुझे RuntimeError: pixmap must be grayscale or rgb to write as pngक्या कोई मदद मिल सकती है?
तिजोरी

5
@vault यह टिप्पणी पुरानी है। आपको "if pix.n <5" को "if pix.n - pix.alpha <4" में बदलना चाहिए क्योंकि मूल स्थिति सही ढंग से CMYK चित्र नहीं ढूँढती है।
ओरिंगा

41

PyPDF2 और तकिया पुस्तकालयों के साथ पायथन में यह सरल है:

import PyPDF2

from PIL import Image

if __name__ == '__main__':
    input1 = PyPDF2.PdfFileReader(open("input.pdf", "rb"))
    page0 = input1.getPage(0)
    xObject = page0['/Resources']['/XObject'].getObject()

    for obj in xObject:
        if xObject[obj]['/Subtype'] == '/Image':
            size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
            data = xObject[obj].getData()
            if xObject[obj]['/ColorSpace'] == '/DeviceRGB':
                mode = "RGB"
            else:
                mode = "P"

            if xObject[obj]['/Filter'] == '/FlateDecode':
                img = Image.frombytes(mode, size, data)
                img.save(obj[1:] + ".png")
            elif xObject[obj]['/Filter'] == '/DCTDecode':
                img = open(obj[1:] + ".jpg", "wb")
                img.write(data)
                img.close()
            elif xObject[obj]['/Filter'] == '/JPXDecode':
                img = open(obj[1:] + ".jp2", "wb")
                img.write(data)
                img.close()

14
प्रारंभ में यह से उत्साहित है, लेकिन यह ऊपर फेंक दिया NotImplementedError: unsupported filter /DCTDecodeया ... /JPXDecodeसे xObject[obj].getData()में पहले दो पीडीएफ के मैं परीक्षण किया गया। विवरण gist.github.com/maphew/fe6ba4bf9ed2bc98ecf5 पर
मैट

4
मैंने हाल ही में PyPDF2 लाइब्रेरी में '/ DCTDecode' संशोधन को आगे बढ़ाया है। आप मेरी रिपॉजिटरी का उपयोग कर सकते हैं: github.com/sylvainpelissier/PyPDF2 जबकि यह मुख्य शाखा में एकीकृत है।
सिल्वेन

1
अपडेट के लिए धन्यवाद, लेकिन खेद है, अभी भी नहीं गया। अपडेट दिया गया। मैं ValueError: not enough image datadctd timecode एम्बेडेड छवियों के लिए और unsupported filter /JPXDecodeएक और pdf पर मिलता है।
मैट विल्की

1
हेडवे बना रहा है! Dctdecode pdf को अब त्रुटि के बिना संसाधित किया जाता है (हालाँकि कभी-कभी आउटपुट चित्र उल्टा होते हैं)। हालाँकि JPXDecode फ़ाइल अब KeyError:/Filterइसके बजाय फेंकता है । मैंने अपने हिसाब से जीआईएस अपडेट किया। पीडीएफ फाइलें 'नेट' से सिर्फ यादृच्छिक होती हैं। जिस्ट के स्रोत लिंक हैं।
मैट विल्की

29
"यह सरल है ... "
मिलीलीटर

34

अक्सर एक पीडीएफ में, छवि को बस के रूप में संग्रहीत किया जाता है। उदाहरण के लिए, एक पीडीएफ के साथ एक पीडीएफ डाला एक बाइट्स की एक सीमा के बीच में कहीं होगा कि जब निकाला एक वैध jpg फ़ाइल है। आप पीडीएफ से बाइट रेंज निकालने के लिए इसका उपयोग कर सकते हैं। मैंने कुछ समय पहले इस बारे में लिखा था, नमूना कोड के साथ: पीडीएफ से जेपीजी को निकालना


1
धन्यवाद नेड। ऐसा लगता है कि विशेष pdf की मुझे इसके लिए आवश्यकता है jpeg इन-सीटू का उपयोग नहीं कर रहा है, लेकिन मैं आपके नमूने को इधर-उधर रख दूंगा क्योंकि यह अन्य चीजों से मेल खाता है।
मैट विल्की

3
क्या आप कृपया कोड में कुछ चीजों की व्याख्या कर सकते हैं? उदाहरण के लिए, आप पहले "स्ट्रीम" और फिर खोज क्यों करेंगे startmark? आप बस खोज शुरू कर सकते हैं startmarkक्योंकि यह JPG नहीं की शुरुआत है? और startfixचर का क्या मतलब है , आप इसे बिल्कुल नहीं बदलते हैं ..
user3599803

यह पीडीएफ के लिए पूरी तरह से काम करता है जिसे मैं छवियों को निकालना चाहता था। (यदि यह किसी और की मदद करता है, तो मैंने उसके कोड को एक .py फ़ाइल के रूप में सहेजा, फिर इसे चलाने के लिए पायथन 2.7.18 स्थापित / उपयोग किया, जो एकल कमांड लाइन तर्क के रूप में मेरी पीडीएफ के लिए मार्ग को पार करता है।)
मैट

25

CCITTFaxDecode फ़िल्टर के लिए PyPDF2 के साथ पायथन में:

import PyPDF2
import struct

"""
Links:
PDF format: http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/pdf_reference_1-7.pdf
CCITT Group 4: https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.6-198811-I!!PDF-E&type=items
Extract images from pdf: http://stackoverflow.com/questions/2693820/extract-images-from-pdf-without-resampling-in-python
Extract images coded with CCITTFaxDecode in .net: http://stackoverflow.com/questions/2641770/extracting-image-from-pdf-with-ccittfaxdecode-filter
TIFF format and tags: http://www.awaresystems.be/imaging/tiff/faq.html
"""


def tiff_header_for_CCITT(width, height, img_size, CCITT_group=4):
    tiff_header_struct = '<' + '2s' + 'h' + 'l' + 'h' + 'hhll' * 8 + 'h'
    return struct.pack(tiff_header_struct,
                       b'II',  # Byte order indication: Little indian
                       42,  # Version number (always 42)
                       8,  # Offset to first IFD
                       8,  # Number of tags in IFD
                       256, 4, 1, width,  # ImageWidth, LONG, 1, width
                       257, 4, 1, height,  # ImageLength, LONG, 1, lenght
                       258, 3, 1, 1,  # BitsPerSample, SHORT, 1, 1
                       259, 3, 1, CCITT_group,  # Compression, SHORT, 1, 4 = CCITT Group 4 fax encoding
                       262, 3, 1, 0,  # Threshholding, SHORT, 1, 0 = WhiteIsZero
                       273, 4, 1, struct.calcsize(tiff_header_struct),  # StripOffsets, LONG, 1, len of header
                       278, 4, 1, height,  # RowsPerStrip, LONG, 1, lenght
                       279, 4, 1, img_size,  # StripByteCounts, LONG, 1, size of image
                       0  # last IFD
                       )

pdf_filename = 'scan.pdf'
pdf_file = open(pdf_filename, 'rb')
cond_scan_reader = PyPDF2.PdfFileReader(pdf_file)
for i in range(0, cond_scan_reader.getNumPages()):
    page = cond_scan_reader.getPage(i)
    xObject = page['/Resources']['/XObject'].getObject()
    for obj in xObject:
        if xObject[obj]['/Subtype'] == '/Image':
            """
            The  CCITTFaxDecode filter decodes image data that has been encoded using
            either Group 3 or Group 4 CCITT facsimile (fax) encoding. CCITT encoding is
            designed to achieve efficient compression of monochrome (1 bit per pixel) image
            data at relatively low resolutions, and so is useful only for bitmap image data, not
            for color images, grayscale images, or general data.

            K < 0 --- Pure two-dimensional encoding (Group 4)
            K = 0 --- Pure one-dimensional encoding (Group 3, 1-D)
            K > 0 --- Mixed one- and two-dimensional encoding (Group 3, 2-D)
            """
            if xObject[obj]['/Filter'] == '/CCITTFaxDecode':
                if xObject[obj]['/DecodeParms']['/K'] == -1:
                    CCITT_group = 4
                else:
                    CCITT_group = 3
                width = xObject[obj]['/Width']
                height = xObject[obj]['/Height']
                data = xObject[obj]._data  # sorry, getData() does not work for CCITTFaxDecode
                img_size = len(data)
                tiff_header = tiff_header_for_CCITT(width, height, img_size, CCITT_group)
                img_name = obj[1:] + '.tiff'
                with open(img_name, 'wb') as img_file:
                    img_file.write(tiff_header + data)
                #
                # import io
                # from PIL import Image
                # im = Image.open(io.BytesIO(tiff_header + data))
pdf_file.close()

यह मेरे लिए तुरंत काम किया, और यह बहुत तेज़ है !! मेरी सभी छवियां उलटी निकलीं, लेकिन मैं OpenCV के साथ इसे ठीक करने में सक्षम था। मैं इसे कॉल करने के लिए ImageMagick का convertउपयोग कर रहा हूं, subprocessलेकिन यह काफी धीमा है। इस समाधान को साझा करने के लिए धन्यवाद
22

2
जैसा कि कहीं और बताया गया है कि आपका tiff_header_structपढ़ना चाहिए '<' + '2s' + 'H' + 'L' + 'H' + 'HHLL' * 8 + 'L'। विशेष रूप 'L'से अंत में ध्यान दें ।
डिस्पेंसर

इस पर कोई मदद कृपया: stackoverflow.com/questions/55899363/…
आकाश बसु

17

Libpoppler "pdfimages" नामक एक टूल के साथ आता है जो ठीक यही करता है।

(ऑनूबंट सिस्टम पर यह पॉपलर-बर्तनों के पैकेज में है)

http://poppler.freedesktop.org/

http://en.wikipedia.org/wiki/Pdfimages

Windows बायनेरिज़: http://blog.alivate.com.au/poppler-windows/


मुझे अच्छा लगेगा अगर किसी को पायथन मॉड्यूल मिला जो कि pdfimagesसबसिस्टम पर स्थापित होने पर भरोसा नहीं करता है ।
user1717828

यह पेजेज़ को आउटपुट नहीं करता है
आलोक नायक

10

मैं मिनीकार्ट को पसंद करता हूं क्योंकि इसका उपयोग करना बेहद आसान है। नीचे दिए गए स्निपेट दिखाते हैं कि कैसे एक पीडीएफ से छवियों को निकालने के लिए:

#pip install minecart
import minecart

pdffile = open('Invoices.pdf', 'rb')
doc = minecart.Document(pdffile)

page = doc.get_page(0) # getting a single page

#iterating through all pages
for page in doc.iter_pages():
    im = page.images[0].as_pil()  # requires pillow
    display(im)

नमस्ते वहाँ, Minecart पूरी तरह से काम करता है, लेकिन मुझे एक छोटी सी समस्या मिली: कभी-कभी छवियों का लेआउट बदल जाता है (क्षैतिज -> ऊर्ध्वाधर)। क्या आपके पास कोई विचार है कि मैं इससे कैसे बच सकता हूं? धन्यवाद!
शा ली

मिनेकार्ट के साथ मुझे: pdfminer.pdftypes.PDFNotImplementedError: असमर्थित फ़िल्टर: / CCITTFaxDecode
Javi12

7

यहां 2019 से मेरा संस्करण है जो पीडीएफ से सभी छवियों को पुन: प्राप्त करता है और उन्हें पीआईएल के साथ पढ़ता है। अजगर 2/3 के साथ संगत। मैंने यह भी पाया कि कभी-कभी पीडीएफ में छवि को zlib द्वारा संपीड़ित किया जा सकता है, इसलिए मेरा कोड डिकंप्रेसन का समर्थन करता है।

#!/usr/bin/env python3
try:
    from StringIO import StringIO
except ImportError:
    from io import BytesIO as StringIO
from PIL import Image
from PyPDF2 import PdfFileReader, generic
import zlib


def get_color_mode(obj):

    try:
        cspace = obj['/ColorSpace']
    except KeyError:
        return None

    if cspace == '/DeviceRGB':
        return "RGB"
    elif cspace == '/DeviceCMYK':
        return "CMYK"
    elif cspace == '/DeviceGray':
        return "P"

    if isinstance(cspace, generic.ArrayObject) and cspace[0] == '/ICCBased':
        color_map = obj['/ColorSpace'][1].getObject()['/N']
        if color_map == 1:
            return "P"
        elif color_map == 3:
            return "RGB"
        elif color_map == 4:
            return "CMYK"


def get_object_images(x_obj):
    images = []
    for obj_name in x_obj:
        sub_obj = x_obj[obj_name]

        if '/Resources' in sub_obj and '/XObject' in sub_obj['/Resources']:
            images += get_object_images(sub_obj['/Resources']['/XObject'].getObject())

        elif sub_obj['/Subtype'] == '/Image':
            zlib_compressed = '/FlateDecode' in sub_obj.get('/Filter', '')
            if zlib_compressed:
               sub_obj._data = zlib.decompress(sub_obj._data)

            images.append((
                get_color_mode(sub_obj),
                (sub_obj['/Width'], sub_obj['/Height']),
                sub_obj._data
            ))

    return images


def get_pdf_images(pdf_fp):
    images = []
    try:
        pdf_in = PdfFileReader(open(pdf_fp, "rb"))
    except:
        return images

    for p_n in range(pdf_in.numPages):

        page = pdf_in.getPage(p_n)

        try:
            page_x_obj = page['/Resources']['/XObject'].getObject()
        except KeyError:
            continue

        images += get_object_images(page_x_obj)

    return images


if __name__ == "__main__":

    pdf_fp = "test.pdf"

    for image in get_pdf_images(pdf_fp):
        (mode, size, data) = image
        try:
            img = Image.open(StringIO(data))
        except Exception as e:
            print ("Failed to read image with PIL: {}".format(e))
            continue
        # Do whatever you want with the image

इस कोड ने मेरे लिए काम किया, जिसमें लगभग कोई संशोधन नहीं था। धन्यवाद।
xax

6

मैंने @sylvain के कोड से शुरुआत की थी, अपवाद जैसी कुछ खामियां थीं NotImplementedError: unsupported filter /DCTDecode getData , या तथ्य यह है कि कोड कुछ पृष्ठों में छवियां खोजने में विफल रहा क्योंकि वे पृष्ठ की तुलना में अधिक गहरे स्तर पर थे।

मेरा कोड है:

import PyPDF2

from PIL import Image

import sys
from os import path
import warnings
warnings.filterwarnings("ignore")

number = 0

def recurse(page, xObject):
    global number

    xObject = xObject['/Resources']['/XObject'].getObject()

    for obj in xObject:

        if xObject[obj]['/Subtype'] == '/Image':
            size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
            data = xObject[obj]._data
            if xObject[obj]['/ColorSpace'] == '/DeviceRGB':
                mode = "RGB"
            else:
                mode = "P"

            imagename = "%s - p. %s - %s"%(abspath[:-4], p, obj[1:])

            if xObject[obj]['/Filter'] == '/FlateDecode':
                img = Image.frombytes(mode, size, data)
                img.save(imagename + ".png")
                number += 1
            elif xObject[obj]['/Filter'] == '/DCTDecode':
                img = open(imagename + ".jpg", "wb")
                img.write(data)
                img.close()
                number += 1
            elif xObject[obj]['/Filter'] == '/JPXDecode':
                img = open(imagename + ".jp2", "wb")
                img.write(data)
                img.close()
                number += 1
        else:
            recurse(page, xObject[obj])



try:
    _, filename, *pages = sys.argv
    *pages, = map(int, pages)
    abspath = path.abspath(filename)
except BaseException:
    print('Usage :\nPDF_extract_images file.pdf page1 page2 page3 …')
    sys.exit()


file = PyPDF2.PdfFileReader(open(filename, "rb"))

for p in pages:    
    page0 = file.getPage(p-1)
    recurse(p, page0)

print('%s extracted images'% number)

यह कोड मेरे लिए '/ ICCBased' / 'FlateDecode' फ़िल्टर की गई छवियों पर विफल हैimg = Image.frombytes(mode, size, data) ValueError: not enough image data
GrantD71

1
@ GrantD71 मैं एक विशेषज्ञ नहीं हूं, और ICCBased के बारे में पहले कभी नहीं सुना। यदि आप इनपुट प्रदान नहीं करते हैं तो प्लस आपकी त्रुटि प्रतिलिपि प्रस्तुत करने योग्य नहीं है।
लाबो

मुझे एक मिलता है KeyError: '/ColorSpace', इसलिए मैं आपकी लाइन को DeviceRGB से बदल दूंगा if '/ColorSpace' not in xObject[obj] or xObject[obj]['/ColorSpace'] == '/DeviceRGB':। वैसे भी, यह मेरे लिए अंत में काम नहीं आया क्योंकि चित्र शायद PNG थे (निश्चित नहीं)।
बसज

@Basj मेरा कोड PNG के साथ भी काम करने वाला है। का मूल्य क्या है xObject[obj]['/Filter']?
लाबो

2
मैंने पायथन 2 और 3 पर काम करने के लिए आपके कोड को अनुकूलित किया। 3. मैंने रोनन पैक्सो से / इंडेक्स किए गए बदलाव को भी लागू किया। मैंने फ़िल्टर को भी बदल दिया है अगर / elif बराबर होने के बजाय 'in' हो। मेरे पास / फ़िल्टर प्रकार ['/ ASCII85Decode', '/ FlateDecode'] के साथ एक पीडीएफ था। मैंने फ़ाइल में लिखने के बजाय छवि को वापस करने के लिए फ़ंक्शन को भी बदल दिया। अद्यतन कोड यहां पाया जा सकता है: gist.github.com/gstorer/f6a9f1dfe41e8e64dcf58d07afa9ab2a
Gerald

4

मैंने अपने सर्वर पर ImageMagick स्थापित किया और फिर इसके माध्यम से कमांडलाइन-कॉल चलाएं Popen:

 #!/usr/bin/python

 import sys
 import os
 import subprocess
 import settings

 IMAGE_PATH = os.path.join(settings.MEDIA_ROOT , 'pdf_input' )

 def extract_images(pdf):
     output = 'temp.png'
     cmd = 'convert ' + os.path.join(IMAGE_PATH, pdf) + ' ' + os.path.join(IMAGE_PATH, output)
     subprocess.Popen(cmd.split(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE)

यह हर पेज के लिए एक इमेज बनाएगा और उन्हें temp-0.png, temp-1.png .... के रूप में संग्रहीत करेगा। यह केवल 'निष्कर्षण' है, अगर आपको केवल छवियों के साथ एक पीडीएफ मिला है और कोई टेक्स्ट नहीं है।


1
छवि मैजिक भूतहास्क्रिप्ट का उपयोग करता है ऐसा करने के लिए। आप इस पोस्ट को घोस्टस्क्रिप्ट कमांड के लिए जाँच सकते हैं जिसे कवर के नीचे इमेज मैजिक उपयोग करता है।
फिलिप कोर्रेया

मेरा कहना है कि कभी-कभी रेंडरिंग बहुत बुरा होता है। पॉपलर के साथ यह बिना किसी समस्या के काम करता है।
रफी

4

कुछ खोज के बाद मुझे निम्नलिखित स्क्रिप्ट मिली जो मेरे पीडीएफ के साथ वास्तव में अच्छी तरह से काम करती है। यह केवल JPG से निपटता है, लेकिन यह पूरी तरह से मेरी असुरक्षित फाइलों के साथ काम करता है। इसके अलावा किसी भी बाहर पुस्तकालयों की आवश्यकता नहीं है।

कोई क्रेडिट नहीं लेने के लिए, स्क्रिप्ट नेड बाथेल्डर से उत्पन्न हुई, न कि मैं। Python3 कोड: पीडीएफ से jpg का अर्क निकालें। जल्दी और गन्दी

import sys

with open(sys.argv[1],"rb") as file:
    file.seek(0)
    pdf = file.read()

startmark = b"\xff\xd8"
startfix = 0
endmark = b"\xff\xd9"
endfix = 2
i = 0

njpg = 0
while True:
    istream = pdf.find(b"stream", i)
    if istream < 0:
        break
    istart = pdf.find(startmark, istream, istream + 20)
    if istart < 0:
        i = istream + 20
        continue
    iend = pdf.find(b"endstream", istart)
    if iend < 0:
        raise Exception("Didn't find end of stream!")
    iend = pdf.find(endmark, iend - 20)
    if iend < 0:
        raise Exception("Didn't find end of JPG!")

    istart += startfix
    iend += endfix
    print("JPG %d from %d to %d" % (njpg, istart, iend))
    jpg = pdf[istart:iend]
    with open("jpg%d.jpg" % njpg, "wb") as jpgfile:
        jpgfile.write(jpg)

    njpg += 1
    i = iend

1
यह दिलचस्प लग रहा है। आपको यह कहाँ से मिला? (और, अपनी पोस्ट में स्वरूपण थोड़ा गड़बड़ है। असंतुलित उद्धरण मुझे लगता है।)
मैट विल्की

1
nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html आप यहाँ मूल पोस्ट पा सकते हैं ...
Max AH Hartvigsen

4

बहुत आसान समाधान:

पॉपलर-बर्तनों के पैकेज का उपयोग करें। इसे स्थापित करने के लिए होमब्रे का उपयोग करें (homebrew MacOS विशिष्ट है, लेकिन आप यहां विधवाओं या लिनक्स के लिए poppler-utils पैकेज पा सकते हैं: https://poppler.freedesktop.org/ )। नीचे दी गई कोड की पहली पंक्ति पॉपलबार-बर्तनों को होमब्रे का उपयोग करके स्थापित करती है। दूसरी पंक्ति को स्थापित करने के बाद (कमांड लाइन से भागो) फिर एक पीडीएफ फाइल से चित्र निकालता है और उन्हें "छवि *" नाम देता है। पायथन के भीतर से इस कार्यक्रम को चलाने के लिए ओएस या सबप्रोसेस मॉड्यूल का उपयोग करें। तीसरी पंक्ति ओएस मॉड्यूल का उपयोग करके कोड है, जो कि उपप्रकार (पायथन 3.5 या बाद में रन () फ़ंक्शन) के साथ एक उदाहरण है। अधिक जानकारी यहाँ: https://www.cyberciti.biz/faq/easily-extract-images-from-pdf-file/

brew install poppler

pdfimages file.pdf image

import os
os.system('pdfimages file.pdf image')

या

import subprocess
subprocess.run('pdfimages file.pdf image', shell=True)

1
धन्यवाद कोल्टन। Homebrew केवल MacOS है। जब निर्देश प्लेटफ़ॉर्म विशिष्ट होते हैं, तो OS को नोट करना अच्छा होता है।
मैट विल्की

@mattwilkie - सिर ऊपर करने के लिए धन्यवाद। मेरे उत्तर में इस पर ध्यान देंगे।
कोल्टन हिक्स

3

मैंने अपने स्वयं के कार्यक्रम के लिए ऐसा किया, और पाया कि उपयोग करने के लिए सबसे अच्छा पुस्तकालय PyMuPDF था। यह आपको प्रत्येक पृष्ठ पर प्रत्येक छवि के "xref" संख्याओं का पता लगाने देता है, और पीडीएफ से कच्ची छवि डेटा निकालने के लिए उनका उपयोग करता है।

import fitz
from PIL import Image
import io

filePath = "path/to/file.pdf"
#opens doc using PyMuPDF
doc = fitz.Document(filePath)

#loads the first page
page = doc.loadPage(0)

#[First image on page described thru a list][First attribute on image list: xref n], check PyMuPDF docs under getImageList()
xref = page.getImageList()[0][0]

#gets the image as a dict, check docs under extractImage 
baseImage = doc.extractImage(xref)

#gets the raw string image data from the dictionary and wraps it in a BytesIO object before using PIL to open it
image = Image.open(io.BytesIO(baseImage['image']))

#Displays image for good measure
image.show()

डॉक्स को निश्चित रूप से देखें, हालाँकि।


सबसे अच्छा विकल्प आईएमओ: fitzविन 10 पर स्थापित होने के बाद , मुझे त्रुटि मिली: ModuleNotFoundError: कोई भी मॉड्यूल जिसका नाम 'फ्रंटएंड' नहीं है, जिसे pip install PyMuPDFयहां चर्चा के रूप में स्थापित करके आसानी से हल किया गया था : stackoverflow.com/questions/564676676-…
पीटर

3

वैसे मैं कई हफ्तों से इससे जूझ रहा था, इनमें से कई जवाबों ने मेरी मदद की, लेकिन हमेशा कुछ न कुछ याद आता रहा, जाहिर तौर पर यहां किसी को भी jbig2 की एनकोडेड इमेज की समस्या नहीं रही

पीडीएफ के उस समूह में जिसे मैं स्कैन कर रहा हूं, jbig2 में एन्कोड किए गए चित्र बहुत लोकप्रिय हैं।

जहां तक ​​मैं समझता हूं कि कई कॉपी / स्कैन मशीनें हैं जो कागजात को स्कैन करती हैं और उन्हें jbig2 एन्कोडेड चित्रों से भरी पीडीएफ फाइलों में बदल देती हैं।

इसलिए कई दिनों के परीक्षण के बाद लंबे समय पहले dkagedal द्वारा यहाँ प्रस्तावित उत्तर के लिए जाने का फैसला किया।

यहाँ लिनक्स पर कदम से कदम रखा गया है: (यदि आपके पास एक और ओएस है, तो मेरा सुझाव है कि एक लिनक्स डॉक का उपयोग करना आसान होगा।)

पहला कदम:

apt-get install poppler-utils

तब मैं कमांड लाइन टूल को चलाने में सक्षम था जिसे pdfimages कहा जाता है:

pdfimages -all myfile.pdf ./images_found/

उपरोक्त कमांड से आप myfile.pdf में मौजूद सभी छवियों को निकाल पाएंगे और आपने उन्हें images_found के अंदर सहेज लिया होगा (आपको पहले images_found बनाना होगा)

सूची में आपको कई प्रकार की छवियां मिलेंगी, png, jpg, tiff; ये सभी किसी भी ग्राफिक टूल के साथ आसानी से पढ़ने योग्य हैं।

फिर आपके पास कुछ फाइलें होंगी जैसे: -145.jb2e और -145.jb2g।

इन 2 फ़ाइलों में एक IMAGE शामिल है jbig2 में एन्कोडेड 2 अलग-अलग फ़ाइलों में से एक हेडर के लिए और एक डेटा के लिए सहेजा गया है

फिर से मैं कई दिनों से यह जानने की कोशिश कर रहा हूँ कि उन फ़ाइलों को किसी पठनीय में कैसे परिवर्तित किया जाए और आखिरकार मुझे jb5252ec नामक इस टूल के बारे में पता चला।

तो सबसे पहले आपको इस मैजिक टूल को इंस्टॉल करना होगा:

apt-get install jbig2dec

तो आप चला सकते हैं:

jbig2dec -t png -145.jb2g -145.jb2e

आप अंततः सभी निकाले गए चित्रों को कुछ उपयोगी में परिवर्तित करने में सक्षम होने जा रहे हैं।

सौभाग्य!


यह उपयोगी जानकारी है और इसे दस्तावेज और साझा किया जाना चाहिए , जैसा कि आपने अभी किया है। +1। हालांकि मैं अपने खुद के नए सवाल और उसके बाद स्वयं जवाब क्योंकि यह अजगर में ऐसा करने का पता नहीं है, जो इस प्र की बात है के रूप में पोस्ट सुझाव देते हैं (cross-लिंक को यह रूप में पदों स्वतंत्र महसूस कर रहा है संबंधित।)
मैट Wilkie

हाय @mwwilkie, सलाह के लिए धन्यवाद, यहाँ सवाल है: stackoverflow.com/questions/60851124/…
Marco

2

फरवरी 2019 तक, @ सिल्वेन (मेरे सेटअप पर कम से कम) द्वारा दिया गया समाधान एक छोटे संशोधन के बिना काम नहीं करता है: xObject[obj]['/Filter']एक मूल्य नहीं है, लेकिन एक सूची है, इस प्रकार स्क्रिप्ट काम करने के लिए, मुझे प्रारूप को संशोधित करना पड़ा जाँच निम्नानुसार है:

import PyPDF2, traceback

from PIL import Image

input1 = PyPDF2.PdfFileReader(open(src, "rb"))
nPages = input1.getNumPages()
print nPages

for i in range(nPages) :
    print i
    page0 = input1.getPage(i)
    try :
        xObject = page0['/Resources']['/XObject'].getObject()
    except : xObject = []

    for obj in xObject:
        if xObject[obj]['/Subtype'] == '/Image':
            size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
            data = xObject[obj].getData()
            try :
                if xObject[obj]['/ColorSpace'] == '/DeviceRGB':
                    mode = "RGB"
                elif xObject[obj]['/ColorSpace'] == '/DeviceCMYK':
                    mode = "CMYK"
                    # will cause errors when saving
                else:
                    mode = "P"

                fn = 'p%03d-%s' % (i + 1, obj[1:])
                print '\t', fn
                if '/FlateDecode' in xObject[obj]['/Filter'] :
                    img = Image.frombytes(mode, size, data)
                    img.save(fn + ".png")
                elif '/DCTDecode' in xObject[obj]['/Filter']:
                    img = open(fn + ".jpg", "wb")
                    img.write(data)
                    img.close()
                elif '/JPXDecode' in xObject[obj]['/Filter'] :
                    img = open(fn + ".jp2", "wb")
                    img.write(data)
                    img.close()
                elif '/LZWDecode' in xObject[obj]['/Filter'] :
                    img = open(fn + ".tif", "wb")
                    img.write(data)
                    img.close()
                else :
                    print 'Unknown format:', xObject[obj]['/Filter']
            except :
                traceback.print_exc()

1
DCTDecode CCITTFaxDecode फ़िल्टर अभी भी कार्यान्वित नहीं हुए हैं।
अभिमन्यु

नमस्कार @Modem राकेश गौड़, क्या आप इस त्रुटि को ट्रिगर करने वाली PDF फ़ाइल प्रदान कर सकते हैं? धन्यवाद!
mxl

दुर्भाग्य से, मैं उस पीडीएफ को साझा नहीं कर सकता।
मॉडम राकेश गौड

या आप अंत में जो पीडीएफ के एक हिस्से को निकालने और केवल उस हिस्से प्रदान कर सकते हैं, या एक्रोबेट (नहीं रीडर, लेकिन प्रो संस्करण), या वैकल्पिक रूप एक और पीडीएफ संपादन प्रोग्राम की तरह एक कार्यक्रम के कब्जे में हो सकता है, बस मुझे दे traceback.print_exc()की दी गई त्रुटि रेखा, ताकि मैं देख सकूं कि किसने इसे ट्रिगर किया; या शायद इस साइट पर यहां दिए गए अन्य समाधानों के लिए विकल्प चुनें, क्योंकि यहां दी गई (मेरी समझ में) एक पीडीएफ से डेटा का 1: 1 दोषरहित निष्कर्षण प्रदान करने पर ध्यान केंद्रित किया गया है और हो सकता है कि आप जो खोज रहे हैं, वह धन्यवाद न हो!
mxl

1

मैंने उन सभी को PyPDFTK में एक साथ यहां जोड़ा

मेरा अपना योगदान /Indexedइस तरह से फाइलों को संभालने का है :

for obj in xObject:
    if xObject[obj]['/Subtype'] == '/Image':
        size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
        color_space = xObject[obj]['/ColorSpace']
        if isinstance(color_space, pdf.generic.ArrayObject) and color_space[0] == '/Indexed':
            color_space, base, hival, lookup = [v.getObject() for v in color_space] # pg 262
        mode = img_modes[color_space]

        if xObject[obj]['/Filter'] == '/FlateDecode':
            data = xObject[obj].getData()
            img = Image.frombytes(mode, size, data)
            if color_space == '/Indexed':
                img.putpalette(lookup.getData())
                img = img.convert('RGB')
            img.save("{}{:04}.png".format(filename_prefix, i))

ध्यान दें कि जब /Indexedफाइलें मिलती हैं, तो आप सिर्फ /ColorSpaceएक स्ट्रिंग की तुलना नहीं कर सकते , क्योंकि यह एक के रूप में आती है ArrayObject। इसलिए, हमें ऐरे को जांचना है और अनुक्रमित पैलेट ( lookupकोड में) को पुनः प्राप्त करना है और इसे पीआईएल इमेज ऑब्जेक्ट में सेट करना है, अन्यथा यह अनइंस्टाल्यूटेड (शून्य) रहता है और पूरी छवि ब्लैक के रूप में दिखाई देती है।

मेरी पहली वृत्ति उन्हें GIFs (जो अनुक्रमित प्रारूप है) के रूप में सहेजने के लिए थी, लेकिन मेरे परीक्षण से पता चला कि PNG छोटे थे और उसी तरह दिखते थे।

फॉक्सिट रीडर पीडीएफ प्रिंटर के साथ पीडीएफ को प्रिंट करते समय मुझे उन प्रकार की छवियां मिलीं।


1

आप pdfimagesउबंटू में भी कमांड का उपयोग कर सकते हैं ।

नीचे दिए गए आदेशों का उपयोग करके पॉपप्लर का उपयोग करें।

sudo apt install poppler-utils

sudo apt-get install python-poppler

pdfimages file.pdf image

बनाई गई फ़ाइलों की सूची (उदाहरण के लिए। पीडीएफ में दो चित्र हैं)

image-000.png
image-001.png

यह काम करता हैं ! अब आप इसे subprocess.runअजगर से चलाने के लिए उपयोग कर सकते हैं ।


1

PyPDF2 का उपयोग करके पदों को पढ़ने के बाद

@ सिल्वेन कोड का उपयोग करते समय त्रुटि NotImplementedError: unsupported filter /DCTDecodeविधि से आना चाहिए .getData(): इसका उपयोग करते समय हल किया जाता है._data बजाय @Alex Paramonov द्वारा गया है।

अब तक मैं केवल "DCTDecode" मामलों से मिला हूं, लेकिन मैं अनुकूलित कोड साझा कर रहा हूं जिसमें विभिन्न पदों से टिप्पणी शामिल है: zilb@Alex Paramonov द्वारा,sub_obj['/Filter'] एक सूची होने के नाते, @ mxl द्वारा।

आशा है कि यह pyPDF2 उपयोगकर्ताओं की मदद कर सकता है। कोड का पालन करें:

    import sys
    import PyPDF2, traceback
    import zlib
    try:
        from PIL import Image
    except ImportError:
        import Image

    pdf_path = 'path_to_your_pdf_file.pdf'
    input1 = PyPDF2.PdfFileReader(open(pdf_path, "rb"))
    nPages = input1.getNumPages()

    for i in range(nPages) :
        page0 = input1.getPage(i)

        if '/XObject' in page0['/Resources']:
            try:
                xObject = page0['/Resources']['/XObject'].getObject()
            except :
                xObject = []

            for obj_name in xObject:
                sub_obj = xObject[obj_name]
                if sub_obj['/Subtype'] == '/Image':
                    zlib_compressed = '/FlateDecode' in sub_obj.get('/Filter', '')
                    if zlib_compressed:
                       sub_obj._data = zlib.decompress(sub_obj._data)

                    size = (sub_obj['/Width'], sub_obj['/Height'])
                    data = sub_obj._data#sub_obj.getData()
                    try :
                        if sub_obj['/ColorSpace'] == '/DeviceRGB':
                            mode = "RGB"
                        elif sub_obj['/ColorSpace'] == '/DeviceCMYK':
                            mode = "CMYK"
                            # will cause errors when saving (might need convert to RGB first)
                        else:
                            mode = "P"

                        fn = 'p%03d-%s' % (i + 1, obj_name[1:])
                        if '/Filter' in sub_obj:
                            if '/FlateDecode' in sub_obj['/Filter']:
                                img = Image.frombytes(mode, size, data)
                                img.save(fn + ".png")
                            elif '/DCTDecode' in sub_obj['/Filter']:
                                img = open(fn + ".jpg", "wb")
                                img.write(data)
                                img.close()
                            elif '/JPXDecode' in sub_obj['/Filter']:
                                img = open(fn + ".jp2", "wb")
                                img.write(data)
                                img.close()
                            elif '/CCITTFaxDecode' in sub_obj['/Filter']:
                                img = open(fn + ".tiff", "wb")
                                img.write(data)
                                img.close()
                            elif '/LZWDecode' in sub_obj['/Filter'] :
                                img = open(fn + ".tif", "wb")
                                img.write(data)
                                img.close()
                            else :
                                print('Unknown format:', sub_obj['/Filter'])
                        else:
                            img = Image.frombytes(mode, size, data)
                            img.save(fn + ".png")
                    except:
                        traceback.print_exc()
        else:
            print("No image found for page %d" % (i + 1))

0

कोड के नीचे प्रयास करें। यह पीडीएफ से सभी छवि को निकाल देगा।

    import sys
    import PyPDF2
    from PIL import Image
    pdf=sys.argv[1]
    print(pdf)
    input1 = PyPDF2.PdfFileReader(open(pdf, "rb"))
    for x in range(0,input1.numPages):
        xObject=input1.getPage(x)
        xObject = xObject['/Resources']['/XObject'].getObject()
        for obj in xObject:
            if xObject[obj]['/Subtype'] == '/Image':
                size = (xObject[obj]['/Width'], xObject[obj]['/Height'])
                print(size)
                data = xObject[obj]._data
                #print(data)
                print(xObject[obj]['/Filter'])
                if xObject[obj]['/Filter'][0] == '/DCTDecode':
                    img_name=str(x)+".jpg"
                    print(img_name)
                    img = open(img_name, "wb")
                    img.write(data)
                    img.close()
        print(str(x)+" is done")

0
  1. सबसे पहले pdf2image इंस्टॉल करें

    पाइप स्थापित करें pdf2image == 1.14.0

  2. पीडीएफ से पृष्ठों की निकासी के लिए नीचे दिए गए कोड का पालन करें।

    file_path="file path of PDF"
    info = pdfinfo_from_path(file_path, userpw=None, poppler_path=None)
    maxPages = info["Pages"]
    image_counter = 0
    if maxPages > 10:
        for page in range(1, maxPages, 10):
            pages = convert_from_path(file_path, dpi=300, first_page=page, 
                    last_page=min(page+10-1, maxPages))
            for page in pages:
                page.save(image_path+'/' + str(image_counter) + '.png', 'PNG')
                image_counter += 1
    else:
        pages = convert_from_path(file_path, 300)
        for i, j in enumerate(pages):
            j.save(image_path+'/' + str(i) + '.png', 'PNG')
    

आशा है कि यह पीडीएफ के पन्नों के अनुसार छवियों के लिए पीडीएफ फाइलों के आसान रूपांतरण के लिए कोडर्स की मदद करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.