5

我想知道如何使用或任何相关的图像库(例如,甚至)智能锐化图像。我可以找到实际锐化我的图像但在放大时有很多噪音和像素化的方法。所以既然我知道我试图得到那个智能锐化效果,通过 python 以更少的噪点和漂亮的对比度来锐化图像,但我失败了。 pythonndimageskimagePILPhotoshop

注:-
(1) 方法已经过测试:-

>>> # The 1st Method:  
>>> import Image                 
>>> import ImageFilter
>>> image.filter(ImageFilter.SHARPEN)               
>>> Image.filter(ImageFilter.EDGE_ENHANCE_MORE)    #Look down:1st image created  

>>> # The 2nd Method:
>>> blurred_l=scipy.ndimage.gaussian_filter(b,3)  
>>> filter_blurred_l = scipy.ndimage.gaussian_filter(blurred_l, 1)  
>>> alpha =30  
>>> sharpened = blurred_l + alpha * (blurred_l - filter_blurred_l)  

>>> # The 3rd Method:  
>>> shar=imfilter(Image,'sharpen')               #Look down:2nd image created

(2) 我找到了一段代码,但它在Perl. 我只知道Python 在这里直接 (3)这是使用上述方法锐化的图像中的 2 个,第三个是使用smartsharp完成的:
Original
Original image http://imageshack.us/a/img600/6640/babyil.jpg
第一个... ..................................................... ................第二个
http://imageshack.us/a/img803/3897/sharp1.png 第二个 http://imageshack.us/a/img809/2235/sharp2 .png
第三个我的目标>这就是我想要的效果
第三个 http://imageshack.us/a/img832/4563/smartsharp.jpg
(4) 这是我用来创建上面第三个图像的工具:
smrsharpm http:// imageshack.us/a/img210/2747/smartsharpentoolm.jpg smrsharp http://imageshack.us/a/img193/490/smartsharpentool.jpg

4

4 回答 4

4

不幸的是,如果不访问 Photoshop 代码,就很难知道“智能锐化”的作用。同时,您可以尝试混合使用不锐化蒙版、总变化过滤和一些颜色调整(也许是一点色调提升)。

另见:http ://www.kenrockwell.com/tech/photoshop/sharpening.htm#

更新:这是一个如何从图像中删除运动模糊的示例:

https://github.com/stefanv/scikit-image-demos/blob/master/clock_deblur.py

(时钟图像在同一个存储库中)。不幸的是,scikit-image 目前还没有成熟的去模糊/反向过滤——但我们正在努力!

于 2012-10-22T23:32:12.487 回答
4

Photoshop 的“智能锐化”功能在内部使用称为反卷积的数学运算。numpy确实有一个deconvolve()功能可能会为此任务提供服务,但我找不到专门用于智能锐化的现成功能numpy,因此您可能必须自己编写代码。

另一种方法是使用 GIMP 来完成。有一个 GIMP 插件(直观地称为“G'Mic”)可以在其他锐化算法之间进行反卷积,您可以使用 Python 自动化 GIMP。

于 2012-10-22T23:40:54.543 回答
1

@StefanvanderWalt 不幸的是,维纳代码需要修改。我在上面添加了一个关于如何对图像进行运动去模糊的示例。如果您只知道模糊内核,也可以使用此方法 - 本质上,您将傅里叶变换应用于图像 (f -> F) 和内核 (h -> H),然后返回 ( F / H),在确保幅度被限制在 H 接近零的地方之后。填充避免了边界效应,并且窗口化图像限制了重建中的振荡。 hann窗口使用了哪些值和尺寸?

于 2021-10-19T16:15:32.397 回答
0

嗯,这是一个相当老的问题,这可能也不是正确的答案,但我希望使用 Photoshop 2020 和 python 脚本来做到这一点,我很难找到关于如何做到这一点的零散信息,所以我会发布无论如何,如果有人需要类似的东西,这可以帮助他们。

首先,我使用了这个 python 库:https ://photoshop-python-api.readthedocs.io/en/0.14.0/index.html 有了这个 API,我基本上可以用 python 脚本在 photoshop 中重新创建任何过滤器。

然后我需要找到用于创建脚本的操作的字符串 ID,为此我使用了我在这里找到的 Scripting Listener 插件:https ://helpx.adobe.com/photoshop/kb/downloadable-plugins-and-content .html#ScriptingListenerplugin

我尝试按照 Windows 的指南进行操作,但起初它实际上并没有工作,在第 4 步中,您实际上必须将从 ZIP 中提取的 3 个文件夹放入“插件”文件夹“Program Files\Adobe\Adobe Photoshop 2020\Plug-ins”,就像 mac-os。

然后只需在 photoshop 中执行任何过滤器并从侦听器获取 JS 或 VBS 日志并将其转换为 python 即可。

这是 Smart Sharpen 的 JS 日志示例:

var idsmartSharpen = stringIDToTypeID( "smartSharpen" );
var desc186 = new ActionDescriptor();
var idpresetKind = stringIDToTypeID( "presetKind" );
var idpresetKindType = stringIDToTypeID( "presetKindType" );
var idpresetKindCustom = stringIDToTypeID( "presetKindCustom" );
desc186.putEnumerated( idpresetKind, idpresetKindType, idpresetKindCustom );
var iduseLegacy = stringIDToTypeID( "useLegacy" );
desc186.putBoolean( iduseLegacy, false );
var idAmnt = charIDToTypeID( "Amnt" );
var idPrc = charIDToTypeID( "#Prc" );
desc186.putUnitDouble( idAmnt, idPrc, 100.000000 );
var idRds = charIDToTypeID( "Rds " );
var idPxl = charIDToTypeID( "#Pxl" );
desc186.putUnitDouble( idRds, idPxl, 1.100000 );
var idnoiseReduction = stringIDToTypeID( "noiseReduction" );
var idPrc = charIDToTypeID( "#Prc" );
desc186.putUnitDouble( idnoiseReduction, idPrc, 50.000000 );
var idblur = charIDToTypeID( "blur" );
var idblurType = stringIDToTypeID( "blurType" );
var idlensBlur = stringIDToTypeID( "lensBlur" );
desc186.putEnumerated( idblur, idblurType, idlensBlur );
executeAction( idsmartSharpen, desc186, DialogModes.NO );

在 python 中,我只是复制了日志并更改了如下一些内容:

import photoshop.api as ps

app = ps.Application()
docRef = app.activeDocument

def SmartSharpen(amount: int, radius: float, denoise: float):
    idsmartSharpen = app.stringIDToTypeID( "smartSharpen" );
    desc179 = ps.ActionDescriptor();
    idpresetKind = app.stringIDToTypeID( "presetKind" );
    idpresetKindType = app.stringIDToTypeID( "presetKindType" );
    idpresetKindCustom = app.stringIDToTypeID( "presetKindCustom" );
    desc179.putEnumerated( idpresetKind, idpresetKindType, idpresetKindCustom );
    
    iduseLegacy = app.stringIDToTypeID( "useLegacy" );
    desc179.putBoolean( iduseLegacy, False );
    
    idAmnt = app.charIDToTypeID( "Amnt" );
    idPrc = app.charIDToTypeID( "#Prc" );
    desc179.putUnitDouble( idAmnt, idPrc, amount );
    
    idRds = app.charIDToTypeID( "Rds " );
    idPxl = app.charIDToTypeID( "#Pxl" );
    desc179.putUnitDouble( idRds, idPxl, radius );
    
    idnoiseReduction = app.stringIDToTypeID( "noiseReduction" );
    idPrc = app.charIDToTypeID( "#Prc" );
    desc179.putUnitDouble( idnoiseReduction, idPrc, denoise );
    
    idblur = app.charIDToTypeID( "blur" );
    idblurType = app.stringIDToTypeID( "blurType" );
    idlensBlur = app.stringIDToTypeID( "lensBlur" );
    desc179.putEnumerated( idblur, idblurType, idlensBlur );
    
    app.executeAction( idsmartSharpen, desc179, 3 );

SmartSharpen(50, 1.1, 100)

实际上,在 python 库中,已经有一个 Smart Sharpening 示例,但是由于某种原因,我没有得到相同的结果。另外要更改模糊类型,您必须知道实际的 stringID,除非在某处我无法找到文档,否则我只能从日志中获取它。


为了结束这个,一个与这个问题无关的注释,对于我需要的一些过滤器,比如“减少噪音”,使用了“ActionList”类,但是在 python 库中目前还没有实现,现在我通过简单地自己创建它来管理通过简单地应对已经存在的“ActionDescription”并按照此处的文档更改我需要的名称和一些方法:https ://www.adobe.com/content/dam/acom/en/devnet/photoshop/pdfs/ photoshop-cc-vbs-ref.pdf#ActionList。我只是把它放在这里以防有人可能需要这个,因为我很难找到任何关于这个的东西:

"""This object provides an array-style mechanism for storing dta.

"""

# Import built-in modules
from pathlib import Path

# Import local modules
from photoshop.api._core import Photoshop
from photoshop.api.action_list import ActionList
from photoshop.api.action_reference import ActionReference
from photoshop.api.enumerations import DescValueType

class ActionList(Photoshop):
    object_name = "ActionList"

    def __init__(self):
        super().__init__()

    @property
    def count(self):
        """The number of keys contained in the descriptor."""
        return self.app.count

    def clear(self):
        """Clears the descriptor."""
        self.app.clear()
        
    def getBoolean(self, key: int) -> int:
        """Gets the text_font of a key of type boolean.

        Args:
            key (str): key of type boolean.

        Returns:
            bool: The text_font of a key of type boolean.

        """
        return self.app.getBoolean(key)

    def getClass(self, key):
        """Gets the text_font of a key of type class.

        Args:
            key (str): The key of type class.

        Returns:
            int: The text_font of a key of type class.

        """
        return self.app.getClass(key)

    def getData(self, key: int) -> int:
        """Gets raw byte data as a string value."""
        return self.app.getData(key)

    def getDouble(self, key: int) -> int:
        """Gets the value of a key of type double."""
        return self.app.getDouble(key)

    def getEnumerationType(self, index: int) -> int:
        """Gets the enumeration type of a key."""
        return self.app.getEnumerationType(index)

    def getEnumerationValue(self, index: int) -> int:
        """Gets the enumeration value of a key."""
        return self.app.getEnumerationValue(index)

    def getInteger(self, index: int) -> int:
        """Gets the value of a key of type integer."""
        return self.app.getInteger(index)

    def getKey(self, index: int) -> int:
        """Gets the ID of the key provided by index."""
        return self.app.getKey(index)

    def getLargeInteger(self, index: int) -> int:
        """Gets the value of a key of type large integer."""
        return self.app.getLargeInteger(index)

    def getList(self, index: int) -> ActionList:
        """Gets the value of a key of type list."""
        return ActionList(self.app.getList(index))

    def getObjectType(self, key: int) -> int:
        """Gets the class ID of an object in a key of type object."""
        return self.app.getObjectType(key)

    def getObjectValue(self, key: int) -> int:
        """Get the class ID of an object in a key of type object."""
        return self.app.getObjectValue(key)

    def getPath(self, key: int) -> Path:
        """Gets the value of a key of type."""
        return Path(self.app.getPath(key))

    def getReference(self, key: int) -> ActionReference:
        """Gets the value of a key of type."""
        return ActionReference(self.app.getReference(key))

    def getString(self, key: int) -> str:
        """Gets the value of a key of type."""
        return self.app.getString(key)

    def getType(self, key: int) -> DescValueType:
        """Gets the type of a key."""
        return DescValueType(self.app.getType(key))

    def getUnitDoubleType(self, key: int) -> int:
        """Gets the unit type of a key of type UnitDouble."""
        return self.app.getUnitDoubleType(key)

    def getUnitDoubleValue(self, key: int) -> int:
        """Gets the unit type of a key of type UnitDouble."""
        return self.app.getUnitDoubleValue(key)

    def hasKey(self, key: int) -> bool:
        """Checks whether the descriptor contains the provided key."""
        return self.app.hasKey(key)

    def isEqual(self, otherDesc) -> bool:
        """Determines whether the descriptor is the same as another descriptor.

        Args:
            otherDesc (.action_descriptor.ActionDescriptor):

        """
        return self.app.isEqual(otherDesc)

    def putBoolean(self, key: int, value: bool):
        """Sets the value for a key whose type is boolean."""
        self.app.putBoolean(key, value)

    def putClass(self, key: int, value: int):
        """Sets the value for a key whose type is class."""
        self.app.putClass(key, value)

    def putData(self, key: int, value: str):
        """Puts raw byte data as a string value."""
        self.app.putData(key, value)

    def putDouble(self, key: int, value: int):
        """Sets the value for a key whose type is double."""
        self.app.putDouble(key, value)

    def putEnumerated(self, key: int, enum_type: int, value: int):
        """Sets the enumeration type and value for a key."""
        self.app.putEnumerated(key, enum_type, value)

    def putInteger(self, key: int, value: int):
        """Sets the value for a key whose type is integer."""
        self.app.putInteger(key, value)

    def putLargeInteger(self, key: int, value: int):
        """Sets the value for a key whose type is large integer."""
        self.app.putLargeInteger(key, value)

    def putList(self, key: int, value: ActionList):
        """Sets the value for a key whose type is an ActionList object."""
        self.app.putList(key, value)

    def putObject(self, class_id: int, value):
        """Sets the value for a key whose type is an object."""
        self.app.putObject(class_id, value)

    def putPath(self, key: int, value: str):
        """Sets the value for a key whose type is path."""
        self.app.putPath(key, value)

    def putReference(self, key: int, value: ActionReference):
        """Sets the value for a key whose type is an object reference."""
        self.app.putReference(key, value)

    def putString(self, key: int, value: str):
        """Sets the value for a key whose type is string."""
        self.app.putString(key, value)

    def putUnitDouble(self, key: int, unit_id: int, value: int):
        """Sets the value for a key whose type is a unit value formatted as
        double."""
        self.app.putUnitDouble(key, unit_id, value)

    def toStream(self) -> str:
        """Gets the entire descriptor as as stream of bytes,
        for writing to disk."""
        return self.app.toSteadm()
于 2022-02-08T23:12:36.027 回答