一个numpy int64的坑

本文介绍了一个关于使用TensorFlow进行预测时遇到的JSON序列化错误,并详细解释了如何排查并解决该问题,主要涉及到numpy.int64类型与Python原生整型之间的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天跑一个tensorflow代码,由于最后结果需要导出为json的文件,所以采用了json.dumps直接写文件,但是一直报错:

Traceback (most recent call last):
  File "predict_test.py", line 62, in <module>
    json.dump(submit, fw)
  File "/home/tensorflow/.pyenv/versions/3.5.3/lib/python3.5/json/__init__.py", line 178, in dump
    for chunk in iterable:
  File "/home/tensorflow/.pyenv/versions/3.5.3/lib/python3.5/json/encoder.py", line 427, in _iterencode
    yield from _iterencode_list(o, _current_indent_level)
  File "/home/tensorflow/.pyenv/versions/3.5.3/lib/python3.5/json/encoder.py", line 324, in _iterencode_list
    yield from chunks
  File "/home/tensorflow/.pyenv/versions/3.5.3/lib/python3.5/json/encoder.py", line 403, in _iterencode_dict
    yield from chunks
  File "/home/tensorflow/.pyenv/versions/3.5.3/lib/python3.5/json/encoder.py", line 324, in _iterencode_list
    yield from chunks
  File "/home/tensorflow/.pyenv/versions/3.5.3/lib/python3.5/json/encoder.py", line 436, in _iterencode
    o = _default(o)
  File "/home/tensorflow/.pyenv/versions/3.5.3/lib/python3.5/json/encoder.py", line 179, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: 26 is not JSON serializable

输入图片说明

蒙蔽了很久,怎么26这个数字不可以serializable??

定位到报错代码位置,报错代码如下:

top_indices = []
submit = []
for i in range(n):
    diction = {}
    diction["label_id"] = list(preds[i].argsort()[-3:][::-1])
    diction["image_id"] = id_list[i]
    submit.append(diction)

with open('submit.plk','w') as fw:
    json.dump(submit, fw)

好像没有什么问题呀~??

做了个小测试:

In [2]: a = submit[1]

In [3]: a
Out[3]: 
{'image_id': 'c532ed79f6c54fb3cf8c45004656e385079a5284.jpg',
 'label_id': [25, 13, 15]}

In [4]: b = {'image_id': 'c532ed79f6c54fb3cf8c45004656e385079a5284.jpg',
   ...:  'label_id': [25, 13, 15]}

In [5]: json.dumps(b)
Out[5]: '{"image_id": "c532ed79f6c54fb3cf8c45004656e385079a5284.jpg", "label_id": [25, 13, 15]}'

In [6]: a == b
Out[6]: True

In [7]: json.dumps(a)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-373a2a7edfd2> in <module>()
...
TypeError: 25 is not JSON serializable

明明a 的值 和b 相等,为什么b就可以json.dumps,而 a json.dumps报错,懵逼一会,想想要不查看下25这个对象,原来对于a来说 25 是一个<type 'numpy.int64'>!!!

被狠狠地坑了半个小时~~由于平时做数据处理大家会经常用到numpy的array,所以大家也要注意,虽然都是整形,但numpy.int64和python的整数是不一样的,解决方案,可以用astype('in32t')或者直接用python的int()方法。

转载于:https://my.oschina.net/Kanonpy/blog/1543791

### 回答1: 可以使用种子生长算法,识别月球撞击轮廓,并返回位置坐标和大小和深度以及识别后轮廓图片的代码如下: ``` #include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp>// 函数声明 cv::Mat seedGrow(cv::Mat src, cv::Point2i seedPoint, int connect_way); int getValue(cv::Mat src, int x, int y, int connect_way);int main(int argc, char **argv) { // 读取图片 cv::Mat src = cv::imread("moon_crater.jpg"); if(src.empty()) { std::cout << "Cannot open the image." << std::endl; return -1; } // 转换为灰度图像 cv::Mat gray; cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY); // 定义种子点位置 cv::Point2i seedPoint(100, 100); // 连通性定义,4或8 int connect_way = 4; // 种子生长 cv::Mat dst = seedGrow(gray, seedPoint, connect_way); // 获取轮廓位置坐标和大小和深度 std::vector<std::vector<cv::Point> > contours; cv::findContours(dst, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); cv::Rect rect = cv::boundingRect(contours[0]); int x = rect.x; int y = rect.y; int width = rect.width; int height = rect.height; int depth = cv::contourArea(contours[0]); // 获取识别后轮廓图片 cv::Mat contourImg(src.size(), CV_8UC3, cv::Scalar(0, 0, 0)); cv::drawContours(contourImg, contours, 0, cv::Scalar(255,255,255), 1); // 显示结果 std::cout << "Location: (" << x << "," << y << ")" << std::endl; std::cout << "Size: (" << width << "," << height << ")" << std::endl; std::cout << "Depth: " << depth << std::endl; cv::imshow("Contour Image", contourImg); cv::waitKey(0); return 0; }// 种子生长函数实现 cv::Mat seedGrow(cv::Mat src, cv::Point2i seedPoint, int connect_way) { cv::Mat dst = cv::Mat::zeros(src.size(), CV_8U); // 目标图像 cv::Mat isGrow(src.size(), CV_8U, cv::Scalar(0)); // 标记图像 // 队列 std::queue<cv::Point2i> Q; // 将种子点入队 Q.push(seedPoint); isGrow.at<uchar>(seedPoint) = 1; dst.at<uchar>(seedPoint) = src.at<uchar>(seedPoint); // 遍历队列 while(!Q.empty()) { // 取出队列中的首元素 cv::Point2i p = Q.front(); Q.pop(); // 搜索邻域点 for(int i = -1; i <= 1; i++) { for(int j = -1; j <= 1; j++) { // 判断是否为4或8连通 if(connect_way == 4 && i*j != 0) continue; // 判断邻域点是否满足条件 int x = p.x + i; int y = p.y + j; if(x >= 0 && x < src.cols && y >= 0 && y < src.rows && isGrow.at<uchar>(y, x) == 0) { if(getValue(src, x, y, connect_way) <= getValue(src, p.x, p.y, connect_way)) { dst.at<uchar>(y, x) = src.at<uchar>(y, x); Q.push(cv::Point2i(x, y)); isGrow.at<uchar>(y, x) = 1; } } } } } return dst; }// 获取像素值 int getValue(cv::Mat src, int x, int y, int connect_way) { int sum = 0; int count = 0; for(int i = -1; i <= 1; i++) { for(int j = -1; j <= 1; j++) { // 判断是否为4或8连通 if(connect_way == 4 && i*j != 0) continue; // 计算像素值 int x_p = x + i; int y_p = y + j; if(x_p >= 0 && x_p < src.cols && y_p >= 0 && y_p < src.rows) { sum += src.at<uchar>(y_p, x_p); count++; } } } return sum / count; } ``` ### 回答2: 要编写一个种子生长法识别月球撞击轮廓的算法,可以按照以下步骤进行: 1. 数据预处理:获取月球的影像数据,并对数据进行预处理,包括去除噪声、调整光照等操作,以便识别撞击轮廓。 2. 种子生长法:通过种子生长法来识别撞击轮廓。首先,选择一个种子点,该点应位于一个撞击内部;然后,使用阈值方法对种子点的像素进行分割,将其作为种子集合;接下来,对于每个种子点,根据一定的生长准则(比如像素灰度值相似性、空间邻近性等),逐步生长扩展种子集合,直到无法继续生长。最后,将扩展后的种子集合作为撞击的轮廓。 3. 获得撞击信息:通过分析撞击轮廓,可以计算得到撞击的位置坐标、大小和深度等信息。位置坐标可以采用轮廓的重心来表示,大小可以通过轮廓的像素数目来计算,深度可以通过分析撞击的边缘像素灰度值的变化来估算。 4. 输出结果:根据需求将获得的撞击信息进行输出,可以将位置坐标和大小和深度写入相应的文件中,也可以将识别后的轮廓图片保存下来。 以下是代码的一个大致框架: ```python import cv2 import numpy as np # 数据预处理 image = cv2.imread("moon_image.jpg") # 预处理操作.... # 种子生长法 seeds = [] # 种子集合 # 选择种子点的策略.... while len(seeds) > 0: seed = seeds.pop(0) # 种子生长操作.... # 获得撞击信息 contours, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: # 计算撞击位置坐标、大小和深度等信息.... # 保存识别后的轮廓图片 output_image = cv2.drawContours(image, contours, -1, (0, 255, 0), 2) cv2.imwrite("output_image.jpg", output_image) ``` 以上是一个简单的算法框架,具体的实现需要根据具体需求进行适当调整和完善。 ### 回答3: 编写一个种子生长法识别月球撞击轮廓的代码需要分为几个步骤。首先,读入一张月球表面的图像。然后,通过图像处理方法将图像转换为灰度图像以便之后的处理。接下来,使用特定的阈值方法将灰度图像转换为二值图像。 在得到二值图像后,可以使用种子生长法来识别月球撞击的轮廓。种子生长法基于给定的种子点在相邻像素之间进行生长,从而确定轮廓。通过对种子点进行合适的选择,可以确保正确地识别撞击的轮廓。 一种常用的种子生长法是基于图像的连通性,即一个像素与其相邻像素之间的相似性。我们可以选择一个像素作为种子点,并逐渐生长,直到满足停止条件。停止条件可以是像素的灰度值等于一定的阈值,或者像素之间的距离超过一定的阈值。 在种子生长过程中,可以记录符合条件的像素的位置坐标,并计算撞击的大小和深度。位置坐标可以根据种子点的位置和生长过程中的生长方向计算得到。大小可以通过统计识别到的像素数量来计算。深度可以通过距离种子点的距离来估计,较远的像素可能表示较深的撞击。 最后,可以将识别出的轮廓以及位置、大小和深度的信息保存下来。同时,可以将轮廓和图像合并并显示,以便观察轮廓的准确度。 综上所述,编写一个种子生长法识别月球撞击轮廓的代码需要包括图像处理、阈值处理、种子生长法、位置和大小和深度的计算等多个步骤。具体实现代码可能较为复杂,超过了300字的限制。希望这些步骤的描述对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值