2.3 使用numpy.array访问像素

numpy.array 提供了 item()itemset()函数来访问和修改像素值,而且这两个函数都是经过 优化处理的,能够更大幅度地提高处理效率。在访问及修改像素点的值时,利用 numpy.array 提供的函数比直接使用索引要快得多,同时,这两个函数的可读性也更好。

1. 二值图像及灰度图像

函数 item()能够更加高效地访问图像的像素点,该函数的语法格式为:
item(行,列)
函数 itemset()可以用来修改像素值,其语法格式为:
itemset(索引值,新值)

【例 2.7】使用 Numpy 生成一个二维随机数组,用来模拟一幅灰度图像,并对其像素进行 访问、修改。

 numpy as np
img = np.random.randint(10,99,size=[5,5],dtype=np.uint8)
print("img=\n",img)
print("读取像素点img.item(3,2)=",img.item(3,2))
img.itemset((3,2),255)
print("修改后img=\n",img)
print("修改后的像素点img.item(3,2)=",img.item(3,2))

通过观察输出结果可以发现,语句 img.itemset((3,2),255)将图像第 3 行第 2 列位置上的像素值修改为 255 了

【例 2.8】生成一个灰度图像,让其中的像素值均为随机数。

import cv2
img = np.random.randint(0,255,size=[256,256],dtype=np.uint8)
cv2.imshow("demo",img)
cv2.waitKey()
cv2.destroyAllWindows()

【例 2.9】读取一幅灰度图像,并对其像素值进行访问、修改。

img = cv2.imread("/Users/zhaofeier/Desktop/lenna.bmp",0)
#! 测试数据读取、修改单个像素值
print("读取像素点img.item(3,2)=",img.item(3,2))
img.itemset((3,2),255)
print("修改后像素点img.item(3,2)=",img.item(3,2))

#! 测试修改一个区域的像素值
cv2.imshow("before",img)
for i in range(10,100):
    for j in range(80,100):
        img.itemset((i,j),255)
        
cv2.imshow("after",img)
cv2.waitKey()
cv2.destroyAllWindows()

2. 彩色图像

我们也可以使用函数 item()和函数 itemset()来访问和修改彩色图像的像素值,过程与操作度图像相似,不同之处在于需要补充通道信息。
函数 item()访问 RGB 模式图像的像素值时,其语法格式为:
item(行,列,通道)
函数 itemset()修改(设置)RGB 模式图像的像素值时,其语法格式为:
itemset(三元组索引值,新值)
需要注意,针对 RGB 图像的访问,必须同时指定行、列以及行列索引(通道),例如img.item(a,b,c)。仅仅指定行和列是不可以的。

【例 2.10】使用 Numpy 生成一个由随机数构成的三维数组,用来模拟一幅 RGB 色彩空间的彩色图像,并使用函数 item()和 itemset()来访问和修改它。

img = np.random.randint(10,99,size=[2,4,3],dtype=np.uint8)
print("img=\n",img)
print("读取像素点img[1,2,0]=",img.item(1,2,0))
print("读取像素点img[0,2,1]=",img.item(0,2,1))
print("读取像素点img[1,0,2]=",img.item(1,0,2))
img.itemset((1,2,0),255)
img.itemset((0,2,1),255)
img.itemset((1,0,2),255)
print("修改后img=\n",img)
print("修改后的像素点img[1,2,0]=",img.item(1,2,0))
print("修改后的像素点img[0,2,1]=",img.item(0,2,1))
print("修改后的像素点img[1,0,2]=",img.item(1,0,2))

【例 2.11】生成一幅彩色图像,让其中的像素值均为随机数。

img = np.random.randint(0,255,size=[256,256,3],dtype=np.uint8)
cv2.imshow("demo",img)
cv2.waitKey()
cv2.destroyAllWindows()

【例 2.12】读取一幅彩色图像,并对其像素进行访问、修改。

img = cv2.imread("/Users/zhaofeier/Desktop/lenna.bmp")
cv2.imshow("before",img)
print("访问 img.item(0,0,0)=",img.item(0,0,0)) 
print("访问 img.item(0,0,1)=",img.item(0,0,1))
print("访问 img.item(0,0,2)=",img.item(0,0,2))

for i in range(0,50):
    for j in range(0,100):
        for k in range(0,3):
            img.itemset((i,j,k),255)    #?白色

cv2.imshow("after",img)
cv2.waitKey()
cv2.destroyAllWindows()
print("修改后 img.item(0,0,0)=",img.item(0,0,0)) 
print("修改后 img.item(0,0,1)=",img.item(0,0,1)) 
print("修改后 img.item(0,0,2)=",img.item(0,0,2))
<think>我们遇到了一个IndexError,错误信息明确指出在索引数组时使用了无效的索引类型。在NumPy数组或Python列表中使用索引时,只允许以下几种类型:-整数(例如:`arr[5]`)-切片(例如:`arr[1:5]`)-省略号(`...`,通常用于多维数组)-`numpy.newaxis`(即`None`,用于增加维度)-整数数组(整数列表或数组,用于花式索引)-布尔数组(布尔列表或数组,用于掩码索引)如果你使用了其他类型的索引(比如浮点数、字符串、非布尔数组等),就会触发这个错误。###常见原因及解决方法:####1.**使用浮点数作为索引**```pythonimportnumpyasnparr=np.array([1,2,3])index=2.0#错误:arr[index]#浮点数索引非法```**解决**:将浮点数转换为整数```pythonarr[int(index)]#正确```####2.**使用非整数数组进行花式索引**```pythonindices=[1.0,2.0]#错误:arr[indices]#数组包含浮点数```**解决**:将索引数组转换为整数类型```pythonindices=np.array([1.0,2.0]).astype(int)arr[indices]```####3.**布尔数组长度不匹配**虽然布尔数组是允许的,但如果布尔数组的长度与待索引数组的维度长度不一致,也会报错(但不是这个错误信息)。这个错误通常直接指出长度不匹配。####4.**在应该使用整数索引的地方误用了其他类型**例如,从文件中读取的索引是字符串类型,或者使用了非整数的标量。###示例分析:假设有以下代码:```pythonimportnumpyasnpa=np.array([[1,2,3],[4,5,6]])#尝试使用浮点数索引print(a[0.5])```运行会报错:```IndexError:onlyintegers,slices(`:`),ellipsis(`...`),numpy.newaxis(`None`)andintegerorbooleanarraysarevalidindices```###如何避免?1.在索引前检查索引的数据类型,确保是整数或允许的类型。2.如果索引来自计算(如除法),使用整数转换或四舍五入。3.使用`np.round()`或`astype(int)`转换浮点索引数组。###完整示例(修复):```pythonimportnumpyasnp#错误的示例:浮点索引a=np.array([1,2,3,4])try:print(a[1.5])exceptIndexErrorase:print("错误:",e)#修复:转换为整数(根据需求选择截断或四舍五入)index=1.5#方法1:向下取整print(a[int(index)])#输出:2(索引1)#方法2:四舍五入print(a[round(index)])#输出:2(索引2?注意:四舍五入后是2,索引2对应元素3)#更复杂的索引数组修复float_indices=np.array([0.9,1.1,2.5])int_indices=float_indices.astype(int)#直接截断为整数print(a[int_indices])#[123]#或者四舍五入rounded_indices=np.round(float_indices).astype(int)print(a[rounded_indices])#[113]注意:1.1四舍五入为1(索引1对应2?但四舍五入后是1,索引1对应2,但原数组索引0:1,索引1:2,索引2:3,索引3:4)#注意:四舍五入后的索引可能越界,需要确保在有效范围内。```###总结:此错误通常是由于使用了非法的索引类型(尤其是浮点数)引起的。解决方法是确保索引为整数或允许的类型,并在必要时进行类型转换。§§相关问题§§:1.NumPy中,如何使用布尔数组进行索引?2.什么是NumPy的花式索引(fancyindexing)?请举例说明3.如何安全地将浮点数数组转换为整数索引数组以避免索引越界?4.使用非整数索引时,NumPy为什么会报错而不是自动转换为整数?</think>这个 `IndexError` 是 NumPy 数组或 Python 列表索引操作中常见的错误,表示你使用了无效的索引类型。让我们详细解析这个错误: ### 错误含义 错误信息明确指出: ``` IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices ``` 这表示**你尝试使用 NumPy 不支持的数据类型作为数组索引**。NumPy 只接受以下类型的索引: 1. **整数**:单个整数索引(如 `arr[5]`) 2. **切片**:使用冒号的切片(如 `arr[1:5]`) 3. **省略号**:`...`(用于多维数组) 4. **numpy.newaxis**:`None`(用于增加维度) 5. **整数数组**:整数列表或数组(如 `arr[[0, 2, 4]]`) 6. **布尔数组**:布尔值列表或数组(如 `arr[arr > 5]`) ### 常见原因及解决方法 #### 1. **使用浮点数作为索引** ```python import numpy as np arr = np.array([10, 20, 30]) # 错误示例:使用浮点数索引 print(arr[1.5]) # 触发 IndexError ``` **解决方法**:转换为整数 ```python index = 1.5 print(arr[int(index)]) # 正确:输出 20 ``` #### 2. **使用非整数数组索引** ```python indices = np.array([0.1, 1.2, 2.3]) # 错误示例:浮点数组索引 print(arr[indices]) # 触发 IndexError ``` **解决方法**:转换为整数数组 ```python int_indices = indices.astype(int) print(arr[int_indices]) # 正确:输出 [10, 20, 30] ``` #### 3. **使用字符串作为索引** ```python # 错误示例:字符串索引 print(arr["1"]) # 触发 IndexError ``` **解决方法**:转换为整数 ```python index_str = "1" print(arr[int(index_str)]) # 正确:输出 20 ``` #### 4. **使用不支持的复杂索引表达式** ```python # 错误示例:复杂表达式 print(arr[1 + 2j]) # 复数索引无效 ``` **解决方法**:确保索引是简单数值表达式 ```python index = 1 print(arr[index]) # 正确 ``` ### 实际场景示例 假设你有一个图像处理场景: ```python import numpy as np # 创建一个 3x3 图像矩阵 image = np.array([ [100, 120, 130], [140, 150, 160], [170, 180, 190] ]) # 从文件中读取坐标(可能返回浮点数) x, y = 1.5, 2.0 # 实际可能来自文件读取或计算 try: pixel = image[x, y] # 错误:使用浮点数索引 except IndexError as e: print(f"错误: {e}") # 解决方案:转换为整数 pixel = image[int(x), int(y)] print(f"修正后像素值: {pixel}") # 输出: 160 ``` ### 如何避免此错误 1. **显式类型转换**:对任何外部输入的索引值使用 `int()` 转换 2. **类型检查**:索引前验证数据类型 ```python if not isinstance(index, (int, np.integer)): index = int(index) ``` 3. **使用安全索引函数**: ```python def safe_index(arr, index): return arr[int(index)] ``` 4. **NumPy 专用方法**:对于坐标索引,使用 `np.round()` 或 `np.floor()` ```python x_index = np.round(x).astype(int) ``` ### 特殊情况:布尔索引的正确使用 布尔索引是允许的,但要确保形状匹配: ```python mask = np.array([True, False, True]) print(arr[mask]) # 正确:输出 [10, 30] # 错误:布尔数组形状不匹配 wrong_mask = np.array([True, False]) print(arr[wrong_mask]) # 触发 IndexError: boolean index did not match ``` ### 总结 这个 `IndexError` 的根本原因是**使用NumPy 不支持的数据类型作为索引**。解决方案的核心是: 1. 确保所有索引都是整数类型 2. 显式转换非整数索引 3. 对于数组索引,确保是整数数组或布尔数组 4. 避免使用字符串、浮点数或复杂类型作为索引
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暮棂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值