why does yolov4 model(darknet) plot alots of bounding boxes around an object in one image? - darknet

I'm using yolov4.cfg for training on my dataset.(I'm using this github repository: https://github.com/Abhi-899/YOLOV4-Custom-Object-Detection)
after training 300 iteration, first I didn't get any bounding box for my images.
after searching about this problem, found that I should decrease the threshold. so I changed my 3 yolo layers so:
[yolo]
mask = 6,7,8
anchors = 12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401
classes=3
num=9
jitter=.3
ignore_thresh = 0.07 ############## .7
truth_thresh = 1 ############ 1
random=1
scale_x_y = 1.05
iou_thresh= 0.213 ##############0.213
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
nms_kind=greedynms
beta_nms=0.6
max_delta=5
now, I get alots of bounding boxes!!!
what should I do?
can any one help me?
my output image is in below link:
https://drive.google.com/file/d/1Jm7pAk8a89JgtPPeXLCLhRW_6hpV68l1/view?usp=sharing

Related

How do I get the RGB values from an image in Flutter?

I'm creating a mobile client for my object-detection server. I already have a perfectly-working python client which takes an image as input, sends it to the server in an HTTP request and receives prediction as a json response. I'm trying to achieve the same in Dart which I'm fairly new to.
The python code I have converts the input JPG image into a numpy array of RGB values in the following format (using a 5x4 image as an example)-
[
[[182, 171, 153], [203, 188, 169], [242, 214, 200], [255, 235, 219], [155, 111, 98]],
[[181, 171, 146], [204, 190, 164], [255, 237, 214], [177, 142, 120], [84, 42, 20]],
[[176, 168, 129], [218, 206, 166], [180, 156, 118], [91, 59, 21], [103, 64, 25]],
[[186, 180, 132], [166, 156, 107], [91, 68, 24], [94, 63, 17], [122, 84, 39]]
]
In my dart code, I have attempted to convert the image into a list of 8-bit unsigned integers using-
Uint8List inputImg = (await rootBundle.load("assets/test.jpg")).buffer.asUint8List()
It gives me a long array of over 800 ints for the same 5x4 image.
On testing it with two single-pixel images (one black and one white), a large section of the Uint8List seems to be repeating for each. I isolated the differing sections of the array and they do not correspond with the RGB values expected for the colors (I expected [0 0 0] and [255 255 255], but got something like 255, 0, 63, 250, 0, 255, 0 and 254, 254, 40, 3 for the two respectively)
I just need the RGB values in the image. Would appreciate someone pointing me in the right direction!
Images are normally compressed when they're stored. Based on the file extension, I'm guessing you're using JPEG encoding. This means the data stored in the assets/test.jpg file is not an array of colors. That would be an inefficient use of data storage if everything were done that way. To get that array of colors, you need to decode the image. This can be done with the image package.
To do this, first add the package as a dependency by adding the following to the pubspec.yaml:
dependencies:
image: ^3.0.4
You should follow the same method of obtaining the encoded image data. But you then need to decode it.
final Uint8List inputImg = (await rootBundle.load("assets/test.jpg")).buffer.asUint8List();
final decoder = JpegDecoder();
final decodedImg = decoder.decodeImage(inputImg);
final decodedBytes = decodedImg.getBytes(format: Format.rgb);
decodedBytes contains a single depth list of all your pixel values in RGB format. To get it into your desired format, just loop over the values and add them to a new list.
List<List<List<int>> imgArr = [];
for(int y = 0; y < decodedImage.height; y++) {
imgArr.add([]);
for(int x = 0; x < decodedImage.width; x++) {
int red = decodedBytes[y*decodedImage.width*3 + x*3];
int green = decodedBytes[y*decodedImage.width*3 + x*3 + 1];
int blue = decodedBytes[y*decodedImage.width*3 + x*3 + 2];
imgArr[y].add([red, green, blue]);
}
}
To do this, first add the package as a dependency by adding the following to the pubspec.yaml:
image: ^3.2.0
import image library to your file:
import 'package:image/image.dart' as im;
get brightness of image:
int getBrightness(File file) {
im.Image? image = im.decodeImage(file.readAsBytesSync());
final data = image?.getBytes();
var color= 0;
for (var x = 0; x < data!.length; x += 4) {
final int r = data[x];
final int g = data[x + 1];
final int b = data[x + 2];
final int avg = ((r + g + b) / 3).floor();
color += avg;
}
return (color/ (image!.width * image.height)).floor();
}
Check selected image is dark or light:
bool isImageDark(int brightness) {
return brightness <= 127;
}
Use above method like this:
int brightness = getBrightness(file);
bool isDark= isImageDark(brightness);
Now you can change your icon color based on your background image

Fit of data as a cos^2?

I have collected this data of angles and intensities in lab to show Malus law so I have to fit the I as I=I0*cos^2(theta). I can't succeed with the cftool because it shows a curve totally different from my data, and I can't get a code that works. This is the data I got:
theta = [90, 110, 130, 135, 150, 170, 180, 190, 210, 225, 230, 250, 270, 290, 310,315,330, 350, 365, 370, 390]
I= [0.0030, 0.6240, 1.3060, 1.3320, 0.9610, 0.1900, 0.0160, 0.1970, 1.1250, 1.3480, 1.2900, 0.5660, 0.0030, 0.5750, 1.6170, 1.6760, 1.0850, 0.1380, 0.0940, 0.2250, 1.2340]
Thank you in advance for your help.
Well, I tried to code, but I couldn't get any near perfect match. I considered I0=1:
figure;
plot(theta, I)
hold on;
f = #(theta) cosd(theta)^2;
fplot(f, [0, 400])

moving longitudinal window (moving average?)

I have 12 data points for y and x:-180:30:179. After I plot my data, it looks like a zig-zag pattern and not smooth. To smooth it out, I apply a moving longitudinal window at 30 degrees (i.e., +/-15 deg.). How can I move it forward by one degree at a time, so that the longitudinal window changes like [-15,15], [-14,16], [-13,17], …?
Here is my code so far
%y=data %12datapoint
y=[90, 65, 60, 53, 70, 82, 65, 38, 44, 71, 77, 64];
sum=0;
for x=-180:30:179
for k=1:30
sum=sum+y(x-15+k);
end
avg(x)=sum/30;
sum=0;
end
I might be trying to read between the lines to much. But it sounds like you are not really asking for a moving average. It kind of sounds like you want your "zig-zag" line smoothed out or interpolated. If this is correct you could do something like this:
y=[90, 65, 60, 53, 70, 82, 65, 38, 44, 71, 77, 64];
x = -180:30:179;
newX = -180:1:179; %Every degree
y_spline = interp1(x,y,-180:1:179,'spline');
y_pchip = interp1(x,y,-180:1:179,'pchip');
l(1) = plot(x,y,'Color',[0 0 1],'Marker','s');hold on
l(2) = plot(newX,y_spline,'r');
l(3) = plot(newX,y_pchip,'g');
grid on; legend(l,{'Orig','spline','pchip'});
Take your pick of interpolation methods ... or I could be completely misreading your question.

How to replace the appropriate colors with my own pallette in MATLAB?

I am using MATLAB 2015. I want to reduce the image color count. An RGB image will be segmentated using k-means algorithm. Then mean colors will be replaced with the colors I have.
The colors are (10),
black - [255, 255, 255],
yellow - [255, 255, 0],
orange - [255, 128, 0],
white - [255, 255, 255],
pink - [255, 153, 255],
lavender - [120, 102, 255],
brown - [153, 51, 0],
green - [0, 255, 0],
blue - [0, 0, 255],
red - [255, 0, 0].
I have succeeded clustering the image. Clustered images should be replaced with the nearest color. How can I change those colors after clustering?
In case you don't succeed in finding a way with MATLAB, you can remap the colours in an image at the command line with ImageMagick which is installed on most Linux distros and is available for OSX and Windows too.
First, you would make a swatch of the colours in your palette. You only need do this once obviously:
convert xc:black xc:yellow xc:"rgb(255,128,0)" \
xc:white xc:"rgb(255,153,255)" xc:"rgb(120,102,255)" \
xc:"rgb(153,51,0)" xc:lime xc:blue xc:red \
+append colormap.png
That looks like this (enlarged):
Now, let's assume you have an image like this colorwheel (colorwheel.png):
and you want to apply your palette (i.e. remap the colours to those in your swatch):
convert colorwheel.png +dither -remap colormap.png result.png

why the integral-image contains extra row and column of zeros?

I am learning how to use the integral-images using opencv with Java API, and i created a test that displays the grayscale image before using the integral-image and after using it. the grayscale image is 10 x 10, and when i converted it to the integral-image
i found it 11 x 11 with extra rows of zeros and extra column of zeros as shown below in the output.
please let me know why the integral-image contains extra row and column of zeros?
Code:
public static void main(String[] args) {
MatFactory matFactory = new MatFactory();
FilePathUtils.addInputPath(path_Obj);
Mat bgrMat = matFactory.newMat(FilePathUtils.getInputFileFullPathList().get(0));
Mat gsImg = SysUtils.rgbToGrayScaleMat(bgrMat);
Log.D(TAG, "MainClas", "gsImg.dump(): " + gsImg.dump());
Mat integralMat = new Mat();
Imgproc.integral(gsImg, integralMat, CvType.CV_32F);
Log.D(TAG, "MainClas", "sumMat.dump(): " + integralMat.dump());
}
OutPut:
1: Debug: MainClass -> MainClas: gsImg.dump(): [2, 1, 7, 5, 1, 11, 2, 7, 9, 11;
1, 2, 0, 0, 3, 20, 17, 5, 7, 8;
4, 8, 0, 2, 6, 30, 31, 5, 2, 2;
39, 43, 47, 44, 38, 62, 60, 37, 37, 39;
27, 29, 52, 52, 47, 75, 67, 59, 58, 63;
25, 21, 49, 51, 51, 78, 64, 66, 76, 80;
40, 36, 50, 46, 41, 56, 42, 45, 47, 49;
13, 17, 20, 15, 9, 20, 15, 19, 12, 11;
17, 13, 8, 5, 4, 7, 13, 20, 17, 17;
2, 4, 7, 9, 8, 6, 6, 7, 7, 8]
2: Debug: MainClass -> MainClas: sumMat.dump(): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 2, 3, 10, 15, 16, 27, 29, 36, 45, 56;
0, 3, 6, 13, 18, 22, 53, 72, 84, 100, 119;
0, 7, 18, 25, 32, 42, 103, 153, 170, 188, 209;
0, 46, 100, 154, 205, 253, 376, 486, 540, 595, 655;
0, 73, 156, 262, 365, 460, 658, 835, 948, 1061, 1184;
0, 98, 202, 357, 511, 657, 933, 1174, 1353, 1542, 1745;
0, 138, 278, 483, 683, 870, 1202, 1485, 1709, 1945, 2197;
0, 151, 308, 533, 748, 944, 1296, 1594, 1837, 2085, 2348;
0, 168, 338, 571, 791, 991, 1350, 1661, 1924, 2189, 2469;
0, 170, 344, 584, 813, 1021, 1386, 1703, 1973, 2245, 2533]
That's the intended behavior. Note that the integral image sum(X,Y) in OpenCV is defined as (see documentation here) the sum of pixels in the original image with indices LESS THAN, sum_(x < X, y < Y), not less than or equal to, those of the integral image. Thus sum(0,0) for example will be the sum of zero pixels, defined to be 0. This is also why the resulting sum image has one more row and column than the original.
The reason for this is that it makes it easier to compute sums etc. over blocks of the image and handle them in a uniform way when they include the top and/or left borders.
There are 2 reasons.
First one is purely mathematical. Say you have a row of 3 numbers (pixels). How many possible cumulative sums it generates? the answer is 4. You can take the sum of 0 first pixels, 1 pixel, 2 pixels or all the 3 pixels. The amount of different sums is 4: (0,1,2,3). 4 is exactly 3+1. Equivalently image of width 10 will yield 11 sums for each row and size 10x10 will yield 11x11 sums.
The second reason is for programming simplicity. Integral image is used to calculate sum of any possible rectangle in the image with just 4 actions (sum of 2 corners minus the 2 other corners). The distance between the corners is exactly equals to the size of the rectangle you want to sum. For example if your rectangle has width of 5 pixels than you access the integral image at indices im[i][j] and im[i][j+5]. However if your rectangle covers the entire image width or height this may produce an index that falls out of array by 1. That is why the integral image is stored in a size that is by 1x1 larger than the image
Note: it is possible to store the integral image in an array of the same size as the image. But then the access to the array will be much slower because one will need to test the indices for out of bound. Accessing the integral image at index [-1] must be detected and produce sum of 0, and accessing at index > width will automatically return sum of the entire width.
OpenCV implemented the larger integral images mainly due to speed reasons. The calculation of the sum of rectangle requires only 4 + or - operation and 4 pointers deference. No need to test that pointers fall inside the image as long as the requested rectangle has legal coordinates inside the image
There are architectures that allow accessing array out of bounds (at illegal indices). For example GPU shaders. On those architectures integral image can be implemented in different fashion (size of NxN instead N+1xN+1 or even as pyramid of sums)
Can you manually remove the extra column from the integral image in openCV?
I strongly do not recommend doing so! openCV has a built in code to access the integral image in a specific way. If you remove the first column you will probably cause unpredictable calculations.
Moreover - as I explained, this additional row and column increase the running time by a factor of up to x10 faster (since addition and subtraction are performed by the CPU much faster than if() conditions)
Please note that integral image is a completely different representation of the original image. Not only it has a different size (N+1)x(N+1) but also a different depth. Your original image can be grayscale (store one byte per pixel) while integral image will need typically 4 bytes per pixel (because summation of many pixels require much larger numbers). So anyway integral image will take ~4 times more memory than the original image. You cannot fit integral image in the original image due to different BPP (bits per pixels) so why be bothered by different width and height