The problem is that the linear image correlation does not have any effect on the images and they appear the same as the original image

huangapple go评论121阅读模式
英文:

The problem is that the linear image correlation does not have any effect on the images and they appear the same as the original image

问题

我遇到了这样一个问题,当显示原始图像和校正后的图像时,它们彼此没有区别,线性图像校正没有效果。不知道可能出现什么问题?

from google.colab import drive
from google.colab.patches import cv2_imshow
# 上传图像
drive.mount("/content/drive")
img = cv2.imread('./drive/MyDrive/python/bird/maxresdefault.jpg', cv2.IMREAD_GRAYSCALE)
# 计算最小和最大像素值
r_min = np.min(img)
r_max = np.max(img)
# 线性图像校正
img_corrected = (img - r_min) * 255.0 / (r_max - r_min)
# 将图像转换为8位格式
img_corrected = np.uint8(img_corrected)
img_corrected = cv2.cvtColor(img_corrected, cv2.COLOR_BGR2RGB)
# 显示原始和校正后的图像
cv2_imshow(img)
cv2_imshow(img_corrected)
cv2.imwrite("./drive/MyDrive/python/bird/corrected_image.jpg", img_corrected)
img_corrected = cv2.imread("./drive/MyDrive/python/bird/corrected_image.jpg")
cv2.waitKey(0)
cv2.destroyAllWindows()

原始图像和校正后的图像如下所示。这些图像在任何方面有区别吗?
The problem is that the linear image correlation does not have any effect on the images and they appear the same as the original image
The problem is that the linear image correlation does not have any effect on the images and they appear the same as the original image

英文:

I have encountered such a problem that when displaying the original and corrected images, they do not differ from each other and there is no effect of linear image correction. Don't know what the problem might be?

from google.colab import drive
from google.colab.patches import cv2_imshow
# Uploading an image
drive.mount("/content/drive")
img = cv2.imread('./drive/MyDrive/python/bird/maxresdefault.jpg', cv2.IMREAD_GRAYSCALE)
# Calculating the minimum and maximum pixel values
r_min = np.min(img)
r_max = np.max(img)
# Linear image correction
img_corrected = (img - r_min) * 255.0 / (r_max - r_min)
# Converting an image to an 8-bit format
img_corrected = np.uint8(img_corrected)
img_corrected = cv2.cvtColor(img_corrected, cv2.COLOR_BGR2RGB)
# Displaying the original and corrected images
cv2_imshow(img)
cv2_imshow(img_corrected)
cv2.imwrite("./drive/MyDrive/python/bird/corrected_image.jpg", img_corrected)
img_corrected = cv2.imread("./drive/MyDrive/python/bird/corrected_image.jpg")
cv2.waitKey(0)
cv2.destroyAllWindows()

The original and corrected image are shown below.And do these images differ in any way?
The problem is that the linear image correlation does not have any effect on the images and they appear the same as the original image
The problem is that the linear image correlation does not have any effect on the images and they appear the same as the original image

答案1

得分: 2

如下是已翻译的内容:

如上所述,最小值和最大值非常接近于0和255(实际值为0和254)。

假设 `r_min` = `0` 和 `r_max` = `255`。
将值分配给线性相关公式:

`(img - r_min) * 255.0 / (r_max - r_min)` = `(img - 0) * 255.0 / (255 - 0)`
= `(img - 0) * 1` = `img`

如您所见,输出等于输入(没有变化)。

---

我们可以使用来自我的[以下答案][1]的 `lin_stretch_img` 方法:

```python
def lin_stretch_img(img, low_prc, high_prc):
    """
    应用线性“拉伸” - 低百分位变为0,高百分位变为255。
    结果被剪切到[0, 255]并转换为np.uint8
    """
    lo, hi = np.percentile(img, (low_prc, high_prc))  # 例如:1% - 低百分位,99% - 高百分位

    if lo == hi:
        return np.full(img.shape, 128, np.uint8)  # 保护:如果lo = hi,则返回灰度图像。

    stretch_img = (img.astype(np.float32) - lo) * (255 / (hi - lo))  # 线性拉伸:lo变为0,hi变为255。
    stretch_img = stretch_img.clip(0, 255).astype(np.uint8)  # 剪切范围到[0, 255]并转换为uint8

与将图像在最小和最大值之间进行线性拉伸不同,我们可以在某个较低的百分位数和较高的百分位数之间进行拉伸。

所有低于低百分位数的像素将变为零(输出像素的1%将为黑色)。
所有高于高百分位数的像素将变为255(输出像素的1%将为白色)。
低百分位数和高百分位数之间的像素会被“拉伸”。
这会增加对饱和和“次饱和”像素的对比度。

百分位数为10和90的示例(有点夸张以进行演示):

import cv2
import numpy as np

def lin_stretch_img(img, low_prc, high_prc):
    lo, hi = np.percentile(img, (low_prc, high_prc))  # 例如:1% - 低百分位,99% - 高百分位

    if lo == hi:
        return np.full(img.shape, 128, np.uint8)  # 保护:如果lo = hi,则返回灰度图像。

    stretch_img = (img.astype(np.float32) - lo) * (255 / (hi - lo))  # 线性拉伸:lo变为0,hi变为255。
    stretch_img = stretch_img.clip(0, 255).astype(np.uint8)  # 剪切范围到[0, 255]并转换为uint8
    return stretch_img

img = cv2.imread('maxresdefault.jpg', cv2.IMREAD_GRAYSCALE)
# r_min = np.min(img)  # 0
# r_max = np.max(img)  # 254
# 线性图像校正
low_prc = 10
high_prc = 90
img_corrected = lin_stretch_img(img, low_prc, high_prc)

# 显示原始图像和校正后的图像(在Google colab中没有显示)。
cv2.imshow('img', img)
cv2.imshow('img_corrected', img_corrected)
cv2.waitKey()
cv2.destroyAllWindows()

在上面的示例中,lo = 32hi = 183

(img - lo) * 255.0 / (hi - lo) = (img - 32) * 255.0 / (183 - 32)
= (img - 32) * 1.69

缩放因子为1.69是对比度增加的原因。


输出:
[![enter image description here][3]][3]

在上面的图像中,10%的像素为黑色(值为0),10%为白色(值为255)。


关于计算时间的注意事项:

percentile 计算需要排序 - 排序的复杂度为O(n*log(n))。
如果我们关心实时考虑 - 比如说我们想在C中实现 lin_stretch_img,我们可以在不排序的情况下解决它。

有一种用于查找百分位数的O(n)解决方案。
该解决方案适用于所有值都是整数的情况(即像素类型为 uint8)。

解决方案包括直方图收集、直方图的累积和以及迭代累积和。
在[以下答案][4]中有一个示例。

在Python中可能不会更快,但C实现将更快。


如果您需要更多翻译或其他帮助,请告诉我。

<details>
<summary>英文:</summary>

As commented, the minimum and maximum are very close to 0 and 255 (the actual values are 0 and 254).  

Assume `r_min` = `0` and `r_max` = `255`.  
Assign the values in the linear correlation formula:  

`(img - r_min) * 255.0 / (r_max - r_min)` = `(img - 0) * 255.0 / (255 - 0)`  
= `(img - 0) * 1` = `img`

As you can see, the output is equal to the input (no change).  

---

We may use `lin_stretch_img` method from my [following answer][1]:  

    def lin_stretch_img(img, low_prc, high_prc):
        &quot;&quot;&quot; 
        Apply linear &quot;stretch&quot; - low_prc percentile goes to 0, 
        and high_prc percentile goes to 255.
        The result is clipped to [0, 255] and converted to np.uint8
        &quot;&quot;&quot;
        lo, hi = np.percentile(img, (low_prc, high_prc))  # Example: 1% - Low percentile, 99% - High percentile
    
        if lo == hi:
            return np.full(img.shape, 128, np.uint8)  # Protection: return gray image if lo = hi.
    
        stretch_img = (img.astype(np.float32) - lo) * (255/(hi-lo))  # Linear stretch: lo goes to 0, hi to 255.
        stretch_img = stretch_img.clip(0, 255).astype(np.uint8)  # Clip range to [0, 255] and convert to uint8 

Instead of linear stretching the image between the minimum and maximum, we may stretch between some lower [percentile][2] and upper percentile.  

All the pixels below the lower percentile are going to be zeros (1% of the output pixels are going to be black).  
All the pixels above the upper percentile are going to be 255 (1% of the output pixels are going to be white).  
The pixels between the lower and upper percentile are &quot;stretched&quot; lineary.  
We are going to get higher contrast in expanse of saturated and &quot;sub-saturated&quot; pixels.  

Example with percentiles 10 and 90 (a bit of exaggeration for demonstration):  

    import cv2
    import numpy as np
    
    def lin_stretch_img(img, low_prc, high_prc):
        lo, hi = np.percentile(img, (low_prc, high_prc))  # Example: 1% - Low percentile, 99% - High percentile
    
        if lo == hi:
            return np.full(img.shape, 128, np.uint8)  # Protection: return gray image if lo = hi.
    
        stretch_img = (img.astype(np.float32) - lo) * (255/(hi-lo))  # Linear stretch: lo goes to 0, hi to 255.
        stretch_img = stretch_img.clip(0, 255).astype(np.uint8)  # Clip range to [0, 255] and convert to uint8
        return stretch_img
    
    img = cv2.imread(&#39;maxresdefault.jpg&#39;, cv2.IMREAD_GRAYSCALE)
    #r_min = np.min(img)  # 0
    #r_max = np.max(img)  # 254
    # Linear image correction
    low_prc = 10
    high_prc = 90
    img_corrected = lin_stretch_img(img, low_prc, high_prc)
    
    # Displaying the original and corrected images (without Google colab).
    cv2.imshow(&#39;img&#39;, img)
    cv2.imshow(&#39;img_corrected&#39;, img_corrected)
    cv2.waitKey()
    cv2.destroyAllWindows()

---

In the above example, `lo` = `32` and `hi` = `183`.  

`(img - lo) * 255.0 / (hi - lo)` = `(img - 32) * 255.0 / (183 - 32)`  
= `(img - 32) * 1.69`  

Scaling by 1.69 is the cause for the higher contrast.

---


Output:  
[![enter image description here][3]][3]

In the image above, 10% of the pixels are black (value `0`) and 10% are white (value `255`).

---

Note about computation time:  

The `percentile` computation requires sorting - complexity of sorting is O(n*log(n)).  
In case we care about real-time considerations - say we want to implement `lin_stretch_img` in C, we may solve it without sorting.  

There is an O(n) solution for finding the percentiles.  
The solution applies the case where all values are integers (i.e pixels type is `uint8`).  

The solution applies histogram collection, cumulative sum of histogram, and iterating the cumulative sum.  
There is an example in the [following answer][4].  

It may not be faster in Python, but the C implementation is going to be much faster.


  [1]: https://stackoverflow.com/a/75625939/4926757
  [2]: https://en.wikipedia.org/wiki/Percentile
  [3]: https://i.stack.imgur.com/kuE0U.png
  [4]: https://stackoverflow.com/a/44611551/4926757

</details>



huangapple
  • 本文由 发表于 2023年3月9日 23:48:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75686961.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定